<Предыдущая | Содержание: | Следующая>
СЕПГ
Имя СЕПГ является аббревиатурой редактор потока. Он выполняет редактирование текста в потоке текста, будь то набор указанных файлов или стандартный ввод. СЕПГ это мощная и довольно сложная программа (о ней написаны целые книги), поэтому мы не будем рассматривать ее здесь полностью.
В общем, способ СЕПГ работает, заключается в том, что ему дается либо одна команда редактирования (в командной строке), либо имя файла сценария, содержащего несколько команд, а затем он выполняет эти команды для каждой строки в потоке текста. Вот очень простой пример СЕПГ В бою:
[я @ linuxbox ~] $ эхо "перед" | sed 's / спереди / сзади /'
назад
[я @ linuxbox ~] $ эхо "перед" | sed 's / спереди / сзади /'
назад
В этом примере мы создаем поток текста из одного слова, используя эхо, и передаем его в СЕПГ. СЕПГ, в свою очередь, выполняет инструкцию с / перед / зад / на текст в потоке и в результате производит вывод «обратно». Мы также можем распознать эту команду как повторение команды «подстановки» (поиска и замены) в vi.
Команды в СЕПГ начинаются с одной буквы. В приведенном выше примере команда подстановки представлена буквой s за которым следуют строки поиска и замены, разделенные символом косой черты в качестве разделителя. Выбор символа-разделителя является произвольным. По соглашению часто используется косая черта, но СЕПГ примет в качестве разделителя любой символ, следующий сразу за командой. Мы могли бы выполнить ту же самую команду таким образом:
[я @ linuxbox ~] $ эхо "перед" | sed 's_front_back_'
назад
[я @ linuxbox ~] $ эхо "перед" | sed 's_front_back_'
назад
Если использовать символ подчеркивания сразу после команды, он становится разделителем. Как мы увидим, возможность установить разделитель может быть использована для того, чтобы сделать команды более читабельными.
Большинство команд в СЕПГ может предшествовать адрес, который указывает, какие строки входящего потока будут редактироваться. Если адрес опущен, то команда редактирования - car-
извлекается из каждой строки входящего потока. Самая простая форма адреса - это номер строки. Мы можем добавить еще один к нашему примеру:
[я @ linuxbox ~] $ эхо "перед" | sed '1s / перед / зад /'
назад
[я @ linuxbox ~] $ эхо "перед" | sed '1s / перед / зад /'
назад
Добавление адреса 1 к нашей команде заставляет нашу замену выполняться в первой строке нашего однострочного входного потока. Если мы укажем другое число:
[я @ linuxbox ~] $ эхо "перед" | sed '2s / перед / зад /'
передний
[я @ linuxbox ~] $ эхо "перед" | sed '2s / перед / зад /'
передний
мы видим, что редактирование не выполняется, так как в нашем входном потоке нет строки 2. Адреса могут быть выражены разными способами. Вот самые распространенные:
Таблица 20-7: Обозначение адреса sed
Описание адреса
Описание адреса
n Номер строки, где n является положительным целым числом.
$ Последняя строка.
/RegExp/ Строки, соответствующие базовому регулярному выражению POSIX. Обратите внимание, что регулярное выражение разделяется символами косой черты. При желании регулярное выражение может быть разделено альтернативным символом, указав выражение с помощью \Cregexpc, Где c является альтернативным персонажем.
адрес1,адрес2 Ряд строк от адрес1 в адрес2, включительно. Адреса могут быть любыми из указанных выше форм единого адреса.
первый~шаг Сопоставьте строку, представленную числом первый, то каждая последующая строка в шаг интервалы. Например, 1 ~ 2 относится к каждой строке с нечетным номером, 5 ~ 5 относится к пятой строке, а затем к каждой пятой строке.
адрес1, + п Совпадение адрес1 и следующее n линий.
адр! Соответствовать всем строкам, кроме адр, которая может быть любой из приведенных выше форм.
Мы продемонстрируем различные типы адресов, используя дистрибутивы.txt файл из более раннего
в этой главе. Во-первых, диапазон номеров строк:
[я @ linuxbox ~] $ sed -n '1,5p' distros.txt
SUSE 10.2 12
Fedora 10 11 ноября 25 г.
SUSE 11.0 06
Ubuntu 8.04 04 октября 24 г.
Fedora 8 11 ноября 08 г.
В этом примере мы печатаем диапазон строк, начиная со строки 1 и продолжая до строки 5. Для этого мы используем p команда, которая просто вызывает печать совпадающей строки. Однако, чтобы это было эффективно, мы должны включить опцию -n (опция без автоматической печати), чтобы вызвать СЕПГ по умолчанию не печатать каждую строку.
Далее мы попробуем регулярное выражение:
[я @ linuxbox ~] $ | sed -n '/ SUSE / p' distros.txt |
СУЗЕ 10.2 | 12/07/2006 |
СУЗЕ 11.0 | 06/19/2008 |
СУЗЕ 10.3 | 10/04/2007 |
СУЗЕ 10.1 | 05/11/2006 |
Включив регулярное выражение, разделенное косой чертой / SUSE /, мы можем выделить строки, содержащие его, почти так же, как GREP.
Наконец, мы попробуем отрицание, добавив восклицательный знак (!) по адресу:
[я @ linuxbox ~] $ | sed -n '/ SUSE /! p' distros.txt |
Fedora 10 | 11/25/2008 |
Ubuntu 8.04 | 04/24/2008 |
Fedora 8 | 11/08/2007 |
Ubuntu 6.10 | 10/26/2006 |
Fedora 7 | 05/31/2007 |
Ubuntu 7.10 | 10/18/2007 |
Ubuntu 7.04 | 04/19/2007 |
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 |
Здесь мы видим ожидаемый результат: все строки в файле, кроме тех, которые совпадают с
регулярное выражение.
До сих пор мы рассмотрели два из СЕПГ команды редактирования, s и p. Вот более полный список основных команд редактирования:
Таблица 20-8: Основные команды редактирования sed
Описание команды
Описание команды
= Вывести текущий номер строки.
a Добавить текст после текущей строки.
d Удалить текущую строку.
i Вставить текст перед текущей строкой.
p Распечатать текущую строку. По умолчанию sed печатает каждую строку и редактирует только те строки, которые соответствуют указанному адресу в файле. Поведение по умолчанию можно изменить, указав параметр -n.
q Выход СЕПГ без обработки дополнительных строк. Если
-n опция не указана, выводить текущую строку.
Q Выход СЕПГ без обработки дополнительных строк.
s/RegExp/замена/ Заменить содержимое замена где бы
RegExp найден. замена может включать специальный символ &, что эквивалентно тексту, соответствующему RegExp, К тому же, замена может включать в себя последовательности \1 через \9, которые являются содержанием соответствующих подвыражений в RegExp. Подробнее об этом см. Обсуждение обратные ссылки ниже. После косой черты следует замена, необязательный флаг может быть указан для изменения s поведение команды.
y/set1/set2 Выполните транслитерацию, преобразовав символы из set1 к соответствующим символам в set2, Обратите внимание, что в отличие от tr, СЕПГ требует, чтобы оба набора были одинаковой длины.
Ассоциация s Команда является наиболее часто используемой командой редактирования. Мы продемонстрируем лишь часть его возможностей, отредактировав наш дистрибутивы.txt файл. Ранее мы обсуждали, как поле даты в дистрибутивы.txt не был в «дружественной к компьютеру» форме.
мат. Хотя дата имеет формат ММ / ДД / ГГГГ, было бы лучше (для удобства сортировки), если бы формат был ГГГГ-ММ-ДД. Выполнение этого изменения в файле вручную может занять много времени и привести к ошибкам, но с СЕПГ, это изменение можно выполнить за один шаг:
[я @ linuxbox ~] $ sed 's/\([0-9]\{2\}\)\/\([0-9]\{2\}\)\/\([0-9]\{4\}\
) $ / \ 3- \ 1- \ 2 / 'distros.txt
SUSE 10.2 2006
Fedora 10 2008 ноября 11 г.
SUSE 11.0 2008
Ubuntu 8.04 2008 апреля 04 г.
Fedora 8 2007 ноября 11 г.
SUSE 10.3 2007
Ubuntu 6.10 2006 апреля 10 г.
Fedora 7 2007 ноября 05 г.
Ubuntu 7.10 2007 апреля 10 г.
Ubuntu 7.04 2007 апреля 04 г.
SUSE 10.1 2006
Fedora 6 2006 ноября 10 г.
Fedora 9 2008 ноября 05 г.
Ubuntu 6.06 2006 апреля 06 г.
Ubuntu 8.10 2008 апреля 10 г.
Fedora 5 2006 ноября 03 г.
Ух ты! Теперь это уродливая команда. Но это работает. Всего за один шаг мы изменили формат даты в нашем файле. Это также прекрасный пример того, почему регулярные выражения иногда в шутку называют средством, предназначенным только для записи. Мы можем их написать, но иногда не можем их прочитать. Прежде чем мы соблазнимся в ужасе убежать от этой команды, давайте посмотрим, как она была построена. Во-первых, мы знаем, что команда будет иметь следующую базовую структуру:
sed 's /RegExp/замена/ 'distros.txt
sed 's /RegExp/замена/ 'distros.txt
Наш следующий шаг - найти регулярное выражение, которое будет изолировать дату. Поскольку он находится в формате ММ / ДД / ГГГГ и появляется в конце строки, мы можем использовать такое выражение:
[0-9]{2}/[0-9]{2}/[0-9]{4}$
[0-9]{2}/[0-9]{2}/[0-9]{4}$
что соответствует двум цифрам, косой черте, двум цифрам, косой черте, четырем цифрам и концу строки. Так что позаботится о RegExp, но что насчет замена? Чтобы справиться с этим, мы должны ввести
новая функция регулярных выражений, которая появляется в некоторых приложениях, использующих BRE. Эта функция называется обратные ссылки и работает так: Если последовательность \n появляется в замена в котором n - это число от 1 до 9, последовательность будет ссылаться на соответствующее подвыражение в предыдущем регулярном выражении. Чтобы создать подвыражения, мы просто заключаем их в круглые скобки, например:
([0-9]{2})/([0-9]{2})/([0-9]{4})$
([0-9]{2})/([0-9]{2})/([0-9]{4})$
Теперь у нас есть три подвыражения. Первый содержит месяц, второй - день месяца, а третий - год. Теперь мы можем построить замена следующим образом:
\ 3- \ 1- \ 2
\ 3- \ 1- \ 2
что дает нам год, тире, месяц, тире и день. Теперь наша команда выглядит так:
sed 's/([0-9]{2})/([0-9]{2})/([0-9]{4})$/\3-\1-\2/' distros.txt
sed 's/([0-9]{2})/([0-9]{2})/([0-9]{4})$/\3-\1-\2/' distros.txt
У нас есть две оставшиеся проблемы. Во-первых, лишние косые черты в нашем обычном выражении сбивают с толку СЕПГ когда он пытается интерпретировать s команда. Во-вторых, поскольку СЕПГпо умолчанию принимает только базовые регулярные выражения, некоторые символы в нашем регулярном выражении будут восприниматься как литералы, а не как метасимволы. Мы можем решить обе эти проблемы с помощью либерального применения обратной косой черты, чтобы избежать оскорбительных символов:
sed 's/\([0-9]\{2\}\)\/\([0-9]\{2\}\)\/\([0-9]\{4\}\)$/\3-\1-\2/' dis tros.txt
sed 's/\([0-9]\{2\}\)\/\([0-9]\{2\}\)\/\([0-9]\{4\}\)$/\3-\1-\2/' dis tros.txt
И вот оно!
Еще одна особенность s Команда - это использование необязательных флагов, которые могут следовать за строкой замены. Самым важным из них является g флаг, который предписывает СЕПГ чтобы применить поиск и замену глобально к строке, а не только к первому экземпляру, который используется по умолчанию. Вот пример:
[я @ linuxbox ~] $ эхо "aaabbbccc" | sed 's / b / B /'
аааBbbccc
[я @ linuxbox ~] $ эхо "aaabbbccc" | sed 's / b / B /'
аааBbbccc
Мы видим, что замена была произведена, но только до первого экземпляра буквы «b», а остальные экземпляры остались без изменений. Добавив g flag, мы можем изменить все экземпляры:
[я @ linuxbox ~] $ эхо "aaabbbccc" | sed 's / b / B / g'
аааВВВccc
[я @ linuxbox ~] $ эхо "aaabbbccc" | sed 's / b / B / g'
аааВВВccc
Пока мы дали только СЕПГ одиночные команды через командную строку. Также возможно создавать более сложные команды в файле сценария, используя -f вариант. Для демонстрации мы будем использовать СЕПГ от наших дистрибутивы.txt файл для построения отчета. Наш отчет будет содержать заголовок вверху, наши измененные даты и все имена дистрибутивов, преобразованные в верхний регистр. Для этого нам нужно будет написать скрипт, поэтому мы запустим наш текстовый редактор и введем следующее:
# sed скрипт для создания отчета о дистрибутивах Linux
1 я \
\
Отчет о дистрибутивах Linux \
s/\([0-9]\{2\}\)\/\([0-9]\{2\}\)\/\([0-9]\{4\}\)$/\3-\1-\2/ y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
# sed скрипт для создания отчета о дистрибутивах Linux
1 я \
\
Отчет о дистрибутивах Linux \
s/\([0-9]\{2\}\)\/\([0-9]\{2\}\)\/\([0-9]\{4\}\)$/\3-\1-\2/ y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
Мы сохраним наши СЕПГ сценарий как дистрибутивы.sed и запустите его так:
[я @ linuxbox ~] $ sed -f дистрибутивы.sed дистрибутивы.txt
Отчет о дистрибутивах Linux
SUSE | 10.2 | 2006-12-07 |
FEDORA | 10 | 2008-11-25 |
SUSE | 11.0 | 2008-06-19 |
UBUNTU | 8.04 | 2008-04-24 |
FEDORA | 8 | 2007-11-08 |
SUSE | 10.3 | 2007-10-04 |
UBUNTU | 6.10 | 2006-10-26 |
FEDORA | 7 | 2007-05-31 |
UBUNTU | 7.10 | 2007-10-18 |
UBUNTU | 7.04 | 2007-04-19 |
SUSE | 10.1 | 2006-05-11 |
FEDORA | 6 | 2006-10-24 |
FEDORA | 9 | 2008-05-13 |
UBUNTU | 6.06 | 2006-06-01 |
UBUNTU | 8.10 | 2008-10-30 |
FEDORA | 5 | 2006-03-20 |
# sed скрипт для создания отчета о дистрибутивах Linux
# sed скрипт для создания отчета о дистрибутивах Linux
Как мы видим, наш скрипт дает желаемые результаты, но как он это делает? Давайте еще раз взглянем на наш скрипт. Мы будем использовать кошка пронумеровать строки:
[я @ linuxbox ~] $ кошка -n distros.sed
[я @ linuxbox ~] $ кошка -n distros.sed
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
1 я \
\
Отчет о дистрибутивах Linux \
s/\([0-9]\{2\}\)\/\([0-9]\{2\}\)\/\([0-9]\{4\}\)$/\3-\1-\2/ y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
1 я \
\
Отчет о дистрибутивах Linux \
s/\([0-9]\{2\}\)\/\([0-9]\{2\}\)\/\([0-9]\{4\}\)$/\3-\1-\2/ y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
Первая строка нашего сценария - это комментарий. Как и во многих файлах конфигурации и языках программирования в системах Linux, комментарии начинаются с # после символа, за которым следует текст, читаемый человеком. Комментарии могут быть размещены в любом месте сценария (но не внутри самих команд) и полезны для любых людей, которым может потребоваться идентифицировать и / или поддерживать сценарий.
Строка 2 - пустая строка. Как и в комментариях, для удобства чтения могут быть добавлены пустые строки.
Много СЕПГ Команды поддерживают адреса строк. Они используются, чтобы указать, какие строки ввода должны быть обработаны. Адреса строк могут быть выражены в виде номеров отдельных строк, диапазонов номеров строк и специального номера строки «$», который указывает последнюю строку ввода.
Строки с 3 по 6 содержат текст, который нужно вставить по адресу 1, первой строке ввода. В i за командой следует обратная косая черта-возврат каретки для создания пропущенного возврата каретки или того, что называется символ продолжения строки. Эта последовательность, которая может использоваться во многих случаях, включая сценарии оболочки, позволяет встраивать возврат каретки в поток текста без передачи сигналов интерпретатору (в данном случае СЕПГ), что достигнут конец строки. В i, а также a (который добавляет текст, а не вставляет его) и c (заменяющий текст) команды, позволяют использовать несколько строк текста, если каждая строка, кроме последней, заканчивается символом продолжения строки. Шестая строка нашего скрипта на самом деле является концом вставленного текста и заканчивается простым поворотом каретки, а не символом продолжения строки, сигнализирующим об окончании i команда.
Примечание. Символ продолжения строки образуется обратной косой чертой, за которой следует немедленно
возвратом каретки. Промежуточные пробелы не допускаются.
Строка 7 - это наша команда поиска и замены. Поскольку ему не предшествует адрес, каждая строка во входном потоке подчиняется своему действию.
Строка 8 выполняет транслитерацию строчных букв в прописные. Обратите внимание, что в отличие от tr, y командовать в СЕПГ не поддерживает диапазоны символов (например, [а- я]), а также не поддерживает классы символов POSIX. Опять же, поскольку y Команде не предшествует адрес, она применяется к каждой строке входящего потока.
Людям, которым нравится sed, также нравится ...
sed - очень способная программа, способная выполнять довольно сложные задачи редактирования потоков текста. Чаще всего он используется для простых однострочных задач, а не для длинных скриптов. Многие пользователи предпочитают другие инструменты для более крупных задач. Самые популярные из них - awk и perl. Они выходят за рамки простых инструментов, подобных описанным здесь программам, и простираются до области законченных языков программирования. В частности, perl часто используется вместо сценариев оболочки для многих задач управления системой и администрирования, а также является очень популярным средством веб-разработки. awk более специализирован. Его особая сила - способность манипулировать табличными данными. Он похож на sed в том, что программы awk обычно обрабатывают текстовые файлы построчно, используя схему, аналогичную концепции sed для адреса, за которым следует действие. Хотя и awk, и perl выходят за рамки этой книги, они очень полезны для пользователя командной строки Linux.