355 500 произведений, 25 200 авторов.

Электронная библиотека книг » Уильям Шоттс » Командная строка Linux » Текст книги (страница 17)
Командная строка Linux
  • Текст добавлен: 12 апреля 2017, 12:30

Текст книги "Командная строка Linux"


Автор книги: Уильям Шоттс


Жанр:

   

ОС и Сети


сообщить о нарушении

Текущая страница: 17 (всего у книги 30 страниц)

* – совпадение с элементом ноль или более раз

Подобно метасимволу ?, звездочка (*) обозначает необязательный элемент; однако, в отличие от знака вопроса (?), этот элемент может встречаться любое число раз, а не только единожды. Представьте, что нам нужно проверить, является ли строка предложением. Чтобы удовлетворять нашим требованиям строка должна начинаться с большой буквы, содержать любое число букв верхнего и нижнего регистра и пробелов и заканчиваться точкой. Для поиска совпадений с этим (очень приблизительным) определением предложения воспользуемся следующим регулярным выражением:

[[:upper:]][[:upper:][:lower:] ]*.

Выражение состоит из трех элементов: выражение в квадратных скобках с классом символов [:upper:], выражение в квадратных скобках с двумя классами символов, [:upper:] и [:lower:], и пробелом, и точка, экранированная обратным слешем. Второй элемент сопровождается метасимволом *, поэтому в нашем предложении ему может соответствовать любое число букв верхнего и нижнего регистра и пробелов, следующих за первой буквой верхнего регистра:

[me@linuxbox ~]$ echo «This works.» | grep -E '[[:upper:]][[:upper:][:lower:] ]*.'

This works.

[me@linuxbox ~]$ echo «This Works.» | grep -E '[[:upper:]][[:upper:][:lower:] ]*.'

This Works.

[me@linuxbox ~]$ echo «this does not» | grep -E '[[:upper:]][[:upper:][:lower:] ]*.'

[me@linuxbox ~]$

Первые два примера соответствуют выражению, а третье – нет, потому что в нем отсутствует обязательный первый символ верхнего регистра и завершающая точка.

+ – совпадение с элементом один или более раз

Метасимвол + действует почти так же, как *, но требует совпадения с предыдущим элементом не менее одного раза. Следующему регулярному выражению будут соответствовать только строки, состоящие из групп, насчитывающих один или несколько алфавитных символов и разделенных одиночными пробелами:

^([[:alpha:]]+ ?)+$

Опробуем его:

[me@linuxbox ~]$ echo «This that» | grep -E '^([[:alpha:]]+ ?)+$'

This that

[me@linuxbox ~]$ echo «a b c» | grep -E '^([[:alpha:]]+ ?)+$'

a b c

[me@linuxbox ~]$ echo «a b 9» | grep -E '^([[:alpha:]]+ ?)+$'

[me@linuxbox ~]$ echo «abc  d» | grep -E '^([[:alpha:]]+ ?)+$'

[me@linuxbox ~]$

Как видите, этому выражению не соответствует строка "a b 9", потому что она содержит неалфавитный символ; точно так же ему не соответствует строка "abc  d", потому что между символами c и d в ней присутствует больше одного пробела.

{ } – совпадение с элементом определенное число раз

Метасимволы { и } используются, чтобы выразить минимальное и максимальное число обязательных совпадений. Эти числа можно представить четырьмя возможными способами, как показано в табл. 19.3.

Таблица 19.3. Определение числа совпадений

Спецификатор

Значение

{n}

Предыдущий элемент соответствует, если встречается точно n раз

{n,m}

Предыдущий элемент соответствует, если встречается не менее n и не более m раз

{n,}

Предыдущий элемент соответствует, если встречается n или более раз

{,m}

Предыдущий элемент соответствует, если встречается не более m раз

Возвращаясь к примеру с телефонными номерами, мы воспользуемся этим методом определения повторений, чтобы упростить исходное регулярное выражение

^(?[0-9][0-9][0-9])? [0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]$

до

^(?[0-9]{3})? [0-9]{3}-[0-9]{4}$

Опробуем его:

[me@linuxbox ~]$ echo «(555) 123-4567» | grep -E '^(?[0-9]{3})? [0-9]{3}-

[0-9]{4}$'

(555) 123-4567

[me@linuxbox ~]$ echo «555 123-4567» | grep -E '^(?[0-9]{3})? [0-9]{3}-[0-9]{4}$'

555 123-4567

[me@linuxbox ~]$ echo «5555 123-4567» | grep -E '^(?[0-9]{3})? [0-9]{3}-

[0-9]{4}$'

[me@linuxbox ~]$

Как видите, измененная версия регулярного выражения успешно справляется с проверкой номеров, с круглыми скобками и без них, и отвергает неправильно оформленные номера.

Практические примеры применения регулярных выражений

Рассмотрим несколько уже знакомых команд и посмотрим, как они могут использовать регулярные выражения.

Проверка списка телефонов с помощью grep

В предыдущем примере мы брали телефонные номера по одному и проверяли правильность их оформления. На практике же часто приходится проверять списки телефонов, поэтому давайте создадим такой список. Для этого воспользуемся волшебной магией командной строки. Магией, потому что мы еще не знакомы с большинством команд, привлеченных для решения поставленной задачи, но не волнуйтесь – мы рассмотрим их в последующих главах. Вот это волшебство:

[me@linuxbox ~]$ for i in {1..10}; do echo «(${RANDOM:0:3}) ${RANDOM:0:3}-${RANDOM:0:4}» >> phonelist.txt; done

Эта команда создаст файл с именем phonelist.txt, содержащий 10 телефонных номеров. Если повторить команду, она добавит в список еще 10 номеров. Также можно изменить число 10 ближе к началу команды, чтобы создать больше или меньше номеров. Однако если заглянуть в файл, можно заметить проблему:

[me@linuxbox ~]$ cat phonelist.txt

(232) 298-2265

(624) 381-1078

(540) 126-1980

(874) 163-2885

(286) 254-2860

(292) 108-518

(129) 44-1379

(458) 273-1642

(686) 299-8268

(198) 307-2440

Некоторые номера оформлены неправильно, что очень хорошо для целей демонстрации их проверки с помощью grep.

Было бы полезно просканировать файл в поисках недопустимых номеров и вывести их.

[me@linuxbox ~]$ grep -Ev '^([0-9]{3}) [0-9]{3}-[0-9]{4}$' phonelist.txt

(292) 108-518

(129) 44-1379

[me@linuxbox ~]$

Здесь мы использовали параметр -v, чтобы обратить сопоставление и вывести только строки, не соответствующие указанному выражению.

Само выражение содержит якорные метасимволы на обоих концах и тем самым гарантирует отсутствие дополнительных символов слева и справа от номера. Кроме того, в отличие от примера, приведенного выше, это выражение также требует обязательного наличия круглых скобок в номере.

Поиск необычных имен файлов с помощью find

Команда find поддерживает проверку, основанную на регулярном выражении. Существует одно важное обстоятельство, которое следует помнить, используя регулярные выражения в командах find и grep. Если grep выводит строку, содержащую совпадение с регулярным выражением, то find требует точного совпадения пути с регулярным выражением. В следующем примере команда find использует регулярное выражение для поиска путей к файлам, содержащим любые символы, не входящие в следующее множество:

[-_./0-9a-zA-Z]

В результате такого поиска можно выявить имена файлов и каталогов, содержащие пробелы и другие, потенциально вредные символы:

[me@linuxbox ~]$ find . -regex '.*[^-_./0-9a-zA-Z].*'

Из-за требования точного совпадения всего пути мы добавили элемент .* с обоих концов выражения, замещающий любое количество любых символов (в том числе и отсутствие символов). В середине выражения находится инвертированное выражение в квадратных скобках, содержащее множество символов, допустимых в именах файлов и каталогов.

Поиск файлов с помощью locate

Программа locate поддерживает простые (параметр –regexp) и расширенные (параметр –regex) регулярные выражения. Благодаря этому можно выполнять те же операции, что производились выше с файлами dirlist:

[me@linuxbox ~]$ locate –regex ‚bin/(bz|gz|zip)'

/bin/bzcat

/bin/bzcmp

/bin/bzdiff

/bin/bzegrep

/bin/bzexe

/bin/bzfgrep

/bin/bzgrep

/bin/bzip2

/bin/bzip2recover

/bin/bzless

/bin/bzmore

/bin/gzexe

/bin/gzip

/usr/bin/zip

/usr/bin/zipcloak

/usr/bin/zipgrep

/usr/bin/zipinfo

/usr/bin/zipnote

/usr/bin/zipsplit

Использовав чередование, мы нашли пути, содержащие bin/bz, bin/gz или /bin/zip.

Поиск текста в less и vim

less и vim поддерживают одинаковые способы поиска в тексте. Чтобы выполнить поиск, нажмите клавишу / и введите регулярное выражение. Воспользуемся программой less, чтобы просмотреть содержимое файла phonelist.txt:

[me@linuxbox ~]$ less phonelist.txt

Затем выполним поиск с применением выражения для проверки:

(232) 298-2265

(624) 381-1078

(540) 126-1980

(874) 163-2885

(286) 254-2860

(292) 108-518

(129) 44-1379

(458) 273-1642

(686) 299-8268

(198) 307-2440

~

~

~

/^([0-9]{3}) [0-9]{3}-[0-9]{4}$

less выделит строки с совпадениями, что позволит сразу увидеть недопустимые номера:

(232) 298-2265

(624) 381-1078

(540) 126-1980

(874) 163-2885

(286) 254-2860

(292) 108-518

(129) 44-1379

(458) 273-1642

(686) 299-8268

(198) 307-2440

~

~

~

(END)

Редактор vim поддерживает только простые регулярные выражения, поэтому выражение для поиска должно выглядеть следующим образом:

/([0-9]{3}) [0-9]{3}-[0-9]{4}

Как видите, выражение практически то же самое; различия обусловлены лишь тем, что многие символы, которые в расширенной версии выражений считаются метасимволами, в простой версии интерпретируются как литералы. Они действуют как метасимволы, только если экранировать их символом обратного слеша. В зависимости от конкретных настроек vim совпадения могут быть выделены или нет. Если совпадения не выделяются, попробуйте в командном режиме выполнить команду :hlsearch, чтобы активировать выделение результатов поиска.

ПРИМЕЧАНИЕ

В разных дистрибутивах vim может поддерживать или не поддерживать подсветку результатов поиска в тексте. В Ubuntu, например, по умолчанию включена сильно упрощенная версия vim. В таких системах необходимо установить боле полную версию vim с помощью диспетчера пакетов.

Заключительное замечание

В этой главе мы рассмотрели несколько примеров использования регулярных выражений. Круг практического применения регулярных выражений можно расширить еще больше, если задействовать их для поиска в других приложениях, поддерживающих такую возможность. Например, с их помощью можно выполнять поиск на страницах справочного руководства:

[me@linuxbox ~]$ cd /usr/share/man/man1

[me@linuxbox man1]$ zgrep -El 'regex|regular expression' *.gz

Программа zgrep реализует интерфейс к grep, позволяя читать сжатые файлы. В данном примере выполняется поиск в сжатых файлах первого раздела справочного руководства. Результатом этой команды будет список файлов, содержащих строку regex или regular expression. Как видите, регулярные выражения поддерживаются множеством программ.

Простые регулярные выражения обладают одной интересной особенностью, которую мы пропустили, – обратными ссылками (back references). Они будут рассматриваться в следующей главе.

20. Обработка текста

Все Unix-подобные операционные системы широко используют текстовые файлы для хранения данных разных типов. Этим объясняется такое большое разнообразие инструментов обработки текста. В этой главе мы рассмотрим программы, которые используются для выполнения самых разных манипуляций с текстом. В следующей главе мы продолжим знакомство со средствами обработки текста, уделив больше внимания программам форматирования текста перед печатью и программам, удовлетворяющим другие потребности человека.

В этой главе мы повторно рассмотрим уже знакомые программы и познакомимся с новыми:

• cat – объединяет файлы и выводит их в стандартный вывод.

• sort – сортирует строки из текстовых файлов.

• uniq – сообщает о повторяющихся строках или удаляет их.

• cut – удаляет фрагменты из каждой строки в файлах.

• paste – выполняет слияние строк из файлов.

• join – объединяет строки из двух файлов по общему полю.

• comm – выполняет построчное сравнение двух сортированных файлов.

• diff – выполняет построчное сравнение файлов.

• patch – применяет diff-файл (файл с результатами сравнения командой diff) к оригиналу.

• tr – перекодирует или удаляет символы.

• sed – потоковый редактор для фильтрации и преобразования текста.

• aspell – интерактивная программа проверки орфографии.

Области применения текста

К настоящему моменту мы познакомились с парой текстовых редакторов (nano и vim), рассмотрели несколько конфигурационных файлов и увидели вывод нескольких десятков команд, и все это в текстовом виде. А для чего еще используется текст? Как оказывается, много для чего.

Документы

Многие люди записывают документы в простом текстовом формате. Очевидно, достаточно удобно хранить простые заметки в небольших текстовых файлах, однако и большие документы также можно записывать в простом текстовом формате. Один из популярных подходов состоит в том, чтобы записать большой документ в текстовом формате и затем использовать язык разметки для описания форматирования конечного документа. Многие научные статьи написаны подобным способом, так как системы обработки текста на основе Unix были в числе первых, обеспечивших улучшенную поддержку типографического оформления, так необходимого авторам в технических дисциплинах.

Веб-страницы

Самым популярным в мире форматом электронных документов является, пожалуй, формат веб-страниц. Веб-страницы – это текстовые документы с разметкой HTML (Hypertext Markup Language – язык разметки гипертекста) или XML (Extensible Markup Language – расширяемый язык разметки), описывающей визуальный формат документа.

Электронная почта

Электронная почта является текстовой средой по своей природе. Даже нетекстовые вложения преобразуются в текстовое представление перед передачей. В этом можно убедиться, загрузив электронное письмо и просмотрев его с помощью less. Вы увидите, что письмо начинается с заголовка, описывающего отправителя письма и промежуточные серверы, принимавшие его в процессе доставки, за которым следует тело письма с его содержимым.

Вывод на принтер

В Unix-подобных системах данные выводятся на печать в простом текстовом виде, или, если страница содержит графику, она преобразуется в описание страницы в текстовом формате, известном как PostScript, которое затем посылается программе, генерирующей графические точки для печати на бумаге.

Исходный код программ

Многие программы командной строки, имеющиеся в Unix-подобных системах, были созданы для поддержки системного администрирования и разработки программного обеспечения, и программы обработки текста не исключение. Многие из них предназначались для решения задач, связанных с разработкой программного обеспечения. Важность обработки текста для программистов объясняется тем, что любое программное обеспечение начинает свое существование как текст. Исходный код, часть программы, которую пишет программист, всегда имеет текстовый формат.

А вот и наши старые знакомые!

В главе 6 мы познакомились с некоторыми командами, способными принимать данные не только из аргументов командной строки, но и из стандартного ввода. В той главе мы очень коротко познакомились с ними, но сейчас пришло время более близкого знакомства – мы узнаем, как их можно использовать для обработки текста.

cat – объединение файлов и вывод их в стандартный поток вывода

Программа cat содержит множество интересных параметров. Многие из них используются для улучшенного отображения текстового содержимого. Примером может служить параметр -A, используемый для отображения непечатаемых символов в тексте. Иногда необходимо знать, имеются ли управляющие символы в просматриваемом тексте. Наиболее распространенными из них являются символы табуляции (в противоположность пробелам) и символы возврата каретки, часто представляющие концы строк в текстовых файлах, оформленных в стиле MS-DOS. Другим распространенным вариантом является файл, содержащий строки с завершающими пробелами.

Давайте создадим файл для экспериментов, используя cat как примитивный текстовый процессор. Для этого введем команду cat (указав файл для перенаправления вывода), а следом наш текст, завершив строки нажатием клавиши ENTER и закончив все комбинацией CTRL+D – она сообщит программе cat, что достигнут конец файла. В этом примере мы ввели символ табуляции и добавили в конец строки несколько пробелов:

[me@linuxbox ~]$ cat > foo.txt

        The quick brown fox jumped over the lazy dog12.

[me@linuxbox ~]$

Далее, вызовем cat с параметром -A, чтобы показать текст:

[me@linuxbox ~]$ cat -A foo.txt

^IThe quick brown fox jumped over the lazy dog. $

[me@linuxbox ~]$

Как видите, символ табуляции в тексте представлен парой символов ^I. Эта обычная форма записи означает «CTRL+I», то есть, как оказывается, – символ табуляции. Здесь также видно, что символ $ отмечает истинный конец строки, помогая увидеть дополнительные пробелы в конце строки.

текст в ms-dos и unix

Одна из причин, почему может появиться желание использовать cat для отображения непечатаемых символов в тексте, – необходимость определить присутствие символов возврата каретки. Откуда берутся скрытые возвраты каретки? Из DOS и Windows! В Unix и DOS концы строк в текстовых файлах оформляются по-разному. В Unix строки заканчиваются символом перевода строки (ASCII 10), тогда как в MS-DOS и ее наследницах для этой цели используется последовательность из возврата каретки (ASCII 13) и перевода строки.

Существует несколько способов преобразовать файлы из формата DOS в формат Unix. Во многих системах Linux имеются программы unix2dos и dos2unix для преобразования текстовых файлов в формат DOS и обратно. Однако если в вашей системе нет программы dos2unix, не волнуйтесь. Процесс преобразования текста из формата DOS в формат Unix очень прост – достаточно лишь удалить ненужные возвраты каретки. Это можно сделать с помощью пары программ, с которыми мы познакомимся ниже в этой главе.

Программа cat имеет также параметры, используемые для изменения текста. Наиболее известными являются -n, добавляющий номера строк, и -s, подавляющий вывод множества пустых строк, идущих подряд. Давайте продемонстрируем их:

[me@linuxbox ~]$ cat > foo.txt

The quick brown fox

 

 

jumped over the lazy dog.

[me@linuxbox ~]$ cat -ns foo.txt

     1  The quick brown fox

     2

     3  jumped over the lazy dog.

[me@linuxbox ~]$

В этом примере мы создали новую версию тестового файла foo.txt, содержащую две строки, разделенные двумя пустыми строками. После обработки текста командой cat с параметрами -ns одна пустая строка была удалена, а остальные строки пронумерованы. Хотя это не самая сложная обработка текста, все же это обработка.

sort – сортировка строк текстовых файлов

Программа sort сортирует содержимое стандартного ввода или одного или нескольких файлов, указанных в командной строке, и записывает результаты в стандартный вывод. Применив тот же прием, который мы использовали совместно с командой cat, можно продемонстрировать обработку стандартного ввода.

[me@linuxbox ~]$ sort > foo.txt

c

b

a

[me@linuxbox ~]$ cat foo.txt

a

b

c

После запуска команды мы ввели буквы c, b и a, а затем признак конца файла с помощью комбинации CTRL+D. Затем просмотрели получившийся файл и увидели, что строки в нем отсортированы.

Поскольку sort может принимать несколько файлов в аргументах командной строки, существует возможность объединить множество файлов в один отсортированный файл. Например, если у вас имеется три файла и вам нужно объединить их в один отсортированный файл, это можно выполнить следующим образом:

sort file1.txt file2.txt file3.txt > final_sorted_list.txt

Программа sort имеет несколько интересных параметров. Их неполный список приводится в табл. 20.1.

Таблица 20.1. Часто используемые параметры команды sort

Параметр

Длинный параметр

Описание

–b

–ignore-leading-blanks

По умолчанию сортировка выполняется с учетом содержимого всей строки, начиная с первого символа. Этот параметр заставляет sort игнорировать начальные пробелы в строках и при сортировке начинать сравнение строк с первых непробельных символов

–f

–ignore-case

Выполнять сортировку без учета регистра символов

–n

–numeric-sort

Выполнять сортировку, опираясь на числовые значения строк. Этот параметр позволяет осуществлять сортировку в соответствии с числовыми значениями, а не по алфавиту

–r

–reverse

Сортировать в обратном порядке. Строки в результате будут следовать в порядке убывания, а не возрастания

–k

–key=поле1[,поле2]

Сортировать по ключевым полям, начиная с поля1 и заканчивая полем2, а не по всей строке

–m

–merge

Интерпретировать каждый аргумент как имя предварительно отсортированного файла. Позволяет объединить несколько файлов в общий результат без выполнения дополнительной сортировки

–o

–output=файл

Записать результат сортировки не в стандартный вывод, а в указанный файл

–t

–field-separator=символ

Определяет символ, разделитель полей. По умолчанию в качестве разделителя используются пробелы и символы табуляции

Имена большинства параметров из представленных выше говорят сами за себя, однако некоторые требуют дополнительных пояснений. Прежде всего рассмотрим параметр -n, используемый для сортировки по числовым значениям. Этот параметр позволяет сортировать строки по их числовым значениям. Продемонстрировать действие этого параметра можно на примере сортировки результатов команды du, чтобы определить каталог, занимающий больший объем дискового пространства. Обычно команда du выводит результаты, отсортированные по именам каталогов:

[me@linuxbox ~]$ du -s /usr/share/* | head

252              /usr/share/aclocal

96               /usr/share/acpi-support

8                /usr/share/adduser

196              /usr/share/alacarte

344              /usr/share/alsa

8                /usr/share/alsa-base

12488            /usr/share/anthy

8                /usr/share/apmd

21440            /usr/share/app-install

48               /usr/share/application-registry

В этом примере мы передали результаты по конвейеру программе head, чтобы ограничить число результатов первыми 10 строками. Мы можем изменить эту команду, добавив сортировку по числовым значениям, чтобы получить 10 самых объемных каталогов:

[me@linuxbox ~]$ du -s /usr/share/* | sort -nr | head

509940           /usr/share/locale-langpack

242660           /usr/share/doc

197560           /usr/share/fonts

179144           /usr/share/gnome

146764           /usr/share/myspell

144304           /usr/share/gimp

135880           /usr/share/dict

76508            /usr/share/icons

68072            /usr/share/apps

62844            /usr/share/foomatic

С помощью параметров -nr мы получили сортировку по числовым значениям в обратном порядке, в результате наибольшие значения оказались в начале списка. Такой способ сортировки стал возможен, потому что числовые значения находятся в начале каждой строки. Но как быть, если потребуется отсортировать строки по числовым значениям, находящимся в середине строки, как, например, в результатах команды ls -l?

[me@linuxbox ~]$ ls -l /usr/bin | head

total 152948

–rwxr-xr-x 1 root   root      34824 2012-04-04 02:42 [

–rwxr-xr-x 1 root   root     101556 2011-11-27 06:08 a2p

–rwxr-xr-x 1 root   root      13036 2012-02-27 08:22 aconnect

–rwxr-xr-x 1 root   root      10552 2011-08-15 10:34 acpi

–rwxr-xr-x 1 root   root       3800 2012-04-14 03:51 acpi_fakekey

–rwxr-xr-x 1 root   root       7536 2012-04-19 00:19 acpi_listen

–rwxr-xr-x 1 root   root       3576 2012-04-29 07:57 addpart

–rwxr-xr-x 1 root   root      20808 2012-01-03 18:02 addr2line

–rwxr-xr-x 1 root   root     489704 2012-10-09 17:02 adept_batch

Забудем на время, что ls может сортировать свои результаты по размеру, и выполним сортировку с помощью sort.

[me@linuxbox ~]$ ls -l /usr/bin | sort -nr -k 5 | head

–rwxr-xr-x 1 root   root    8234216 2012-04-07 17:42 inkscape

–rwxr-xr-x 1 root   root    8222692 2012-04-07 17:42 inkview

–rwxr-xr-x 1 root   root    3746508 2012-03-07 23:45 gimp-2.4

–rwxr-xr-x 1 root   root    3654020 2012-08-26 16:16 quanta

–rwxr-xr-x 1 root   root    2928760 2012-09-10 14:31 gdbtui

–rwxr-xr-x 1 root   root    2928756 2012-09-10 14:31 gdb

–rwxr-xr-x 1 root   root    2602236 2012-10-10 12:56 net

–rwxr-xr-x 1 root   root    2304684 2012-10-10 12:56 rpcclient

–rwxr-xr-x 1 root   root    2241832 2012-04-04 05:56 aptitude

–rwxr-xr-x 1 root   root    2202476 2012-10-10 12:56 smbcacls

Программа sort часто вовлекается в обработку табличных данных, таких как результат команды ls выше. Если воспользоваться терминологией баз данных, об этой таблице можно сказать, что каждая строка – это запись и каждая запись состоит из множества полей, таких как атрибуты файла, счетчик ссылок, имя файла, размер файла и т.д. Программа sort способна обрабатывать поля по отдельности. Согласно той же терминологии баз данных, мы можем указать одно или несколько ключевых полей, которые должны использоваться как ключи сортировки. В примере, приведенном выше, мы добавили параметры n и r, чтобы выполнить сортировку по числовым значениям в порядке убывания, а также параметр -k с аргументом 5, чтобы указать, что сортировка должна выполняться по пятому полю.

Параметр очень интересен и обладает множеством любопытных свойств, но прежде чем приступить к их обсуждению, поговорим о том, как sort определяет поля. Рассмотрим очень простой текстовый файл, содержащий единственную строку с именем автора этой книги:

William   Shotts

По умолчанию sort «видит» в этой строке два поля. Первое поле содержит последовательность символов William, второе – последовательность символов Shotts, то есть пробельные символы (пробелы и символы табуляции) интерпретируются как разделители полей, и эти разделители включаются в поле при выполнении сортировки.

Взглянув еще раз на любую строку в выводе нашей команды ls, можно сказать, что она содержит восемь полей и пятое поле хранит размер файла:

–rwxr-xr-x 1 root root 8234216 2012-04-07 17:42 inkscape

Для следующей серии экспериментов возьмем файл с историей выпуска новых версий трех популярных дистрибутивов Linux в период с 2006 по 2008 год. Каждая строка в файле содержит три поля: название дистрибутива, номер версии и дата выпускав формате ММ/ДД/ГГГГ:

SUSE             10.2    12/07/2006

Fedora           10      11/25/2008

SUSE             11.0    06/19/2008

Ubuntu           8.04    04/24/2008

Fedora           8       11/08/2007

SUSE             10.3    10/04/2007

Ubuntu           6.10    10/26/2006

Fedora           7       05/31/2007

Ubuntu           7.10    10/18/2007

Ubuntu           7.04    04/19/2007

SUSE             10.1    05/11/2006

Fedora           6       10/24/2006

Fedora           9       05/13/2008

Ubuntu           6.06    06/01/2006

Ubuntu           8.10    10/30/2008

Fedora           5       03/20/2006

С помощью текстового редактора (например, vim) введите эти данные и сохраните в файле с именем distros.txt.

Далее попробуем отсортировать файл и посмотрим, что из этого получится:

[me@linuxbox ~]$ sort distros.txt

Fedora           10      11/25/2008

Fedora           5       03/20/2006

Fedora           6       10/24/2006

Fedora           7       05/31/2007

Fedora           8       11/08/2007

Fedora           9       05/13/2008

SUSE             10.1    05/11/2006

SUSE             10.2    12/07/2006

SUSE             10.3    10/04/2007

SUSE             11.0    06/19/2008

Ubuntu           6.06    06/01/2006

Ubuntu           6.10    10/26/2006

Ubuntu           7.04    04/19/2007

Ubuntu           7.10    10/18/2007

Ubuntu           8.04    04/24/2008

Ubuntu           8.10    10/30/2008

У нас это почти получилось. Единственная проблема возникла с сортировкой номеров версий Fedora. Так как в лексикографическом смысле 1 предшествует 5, версия 10 оказалась вверху, тогда как версии 9 – внизу.

Чтобы исправить эту ошибку, выполним сортировку по нескольким ключам. Итак, нам нужно выполнить сортировку по первому полю в алфавитном порядке, а затем по второму полю в числовом порядке. Программа sort позволяет указать в командной строке несколько параметров -k, чтобы можно было определить несколько ключей сортировки. В действительности в ключ можно включать диапазон полей. Если диапазон не определен (как в примерах, приведенных выше), sort использует в качестве ключа часть строки, начинающуюся с указанного поля и простирающуюся до конца строки.

Вот как выглядит синтаксис сортировки по нескольким ключам:

[me@linuxbox ~]$ sort –key=1,1 –key=2n distros.txt

Fedora           5       03/20/2006

Fedora           6       10/24/2006

Fedora           7       05/31/2007

Fedora           8       11/08/2007

Fedora           9       05/13/2008

Fedora           10      11/25/2008

SUSE             10.1    05/11/2006

SUSE             10.2    12/07/2006

SUSE             10.3    10/04/2007

SUSE             11.0    06/19/2008

Ubuntu           6.06    06/01/2006

Ubuntu           6.10    10/26/2006

Ubuntu           7.04    04/19/2007

Ubuntu           7.10    10/18/2007

Ubuntu           8.04    04/24/2008

Ubuntu           8.10    10/30/2008

Здесь для ясности использовались имена параметров в длинной форме, однако с тем же успехом можно было бы передать параметры -k 1,1 -k 2n. В аргументе для первого экземпляра параметра ключа мы указали диапазон полей, входящих в первый ключ. Так как сортировка должна выполняться только по первому полю, мы указали диапазон 1,1, что означает: «начиная с поля 1 и заканчивая полем 1». Второму экземпляру мы передали аргумент 2n, который означает: «ключом сортировки является второе поле и сортировка выполняется в порядке числовых значений». В конце определения ключа допускаются однобуквенные имена параметров, они указывают на тип сортировки. Имена этих однобуквенных параметров совпадают с именами глобальных параметров программы sort: b (игнорировать начальные пробелы), n (числовая сортировка), r (сортировка в обратном порядке) и т.д.

Третье поле в списке содержит дату в формате, неудобном для сортировки. В компьютере даты обычно приводятся к виду ГГГГ-ММ-ДД, что упрощает сортировку в хронологическом порядке, но здесь используется американский формат ММ/ДД/ГГГГ. Как же тогда отсортировать этот список в хронологическом порядке?

К счастью, sort предоставляет такую возможность. Параметр –key позволяет определять смещения внутри полей, чтобы в качестве ключей можно было использовать части полей:

[me@linuxbox ~]$ sort -k 3.7nbr -k 3.1nbr -k 3.4nbr distros.txt

Fedora           10      11/25/2008

Ubuntu           8.10    10/30/2008

SUSE             11.0    06/19/2008

Fedora           9       05/13/2008

Ubuntu           8.04    04/24/2008

Fedora           8       11/08/2007

Ubuntu           7.10    10/18/2007

SUSE             10.3    10/04/2007

Fedora           7       05/31/2007

Ubuntu           7.04    04/19/2007

SUSE             10.2    12/07/2006

Ubuntu           6.10    10/26/2006

Fedora           6       10/24/2006

Ubuntu           6.06    06/01/2006

SUSE             10.1    05/11/2006

Fedora           5       03/20/2006

Добавив параметр -k 3.7, мы сообщили программе sort, что она должна использовать для сортировки ключ, начинающийся с седьмого символа в третьем поле, который соответствует началу года. Аналогично, параметры -k 3.1 и -k 3.4 определяют ключи сортировки по месяцу и дню месяца. Мы также добавили параметры n и r, чтобы выполнить числовую сортировку в обратном порядке. Параметр b добавлен для исключения начальных пробелов из поля с датой (число которых в разных строках отличается и тем самым влияет на результат сортировки).


    Ваша оценка произведения:

Популярные книги за неделю