- HuMan: sed
- Введение
- Команда s — substitution (замена)
- Регулярные выражения (РВ)
- Использование символа & когда ОБРАЗЕЦ неизвестен
- Использование условных знаков \(, \) и
для обработки части ОБРАЗЦА
- Модификаторы замены команды s
- Модификатор /g
- Как выбрать нужное совпадение из нескольких
- Числовой модификатор
- Модификатор /p — выдавать на стандартный выход (печатать — print)
- Модификатор /w
- Модификатор /e (расширение GNU)
- Модификаторы /I и /i (расширение GNU)
- Комбинации модификаторов
- Условные обозначения (расширение GNU)
- Опции программы sed
- Опция -e
- Опция -f
- Опция -n
- Выбор нужных элементов редактируемого текста
- Выбор строк по номерам
- Выбор строк в диапазоне номеров
- Выбор строк, содержащих некое выражение
- Выбор строк в диапазоне между двумя выражениями
- Выбор строк от начала файла и до некоего выражения
- Выбор строк от некоего выражения и до конца файла
- Другие команды редактора sed
- Команда d (delete)
- Команда p (print)
- Команда !
- Команда q (quit)
- Команда w (write)
- Команда r (read)
- Команда =
- Команда y
- Скрипты программы sed
- Программа sed и символы кириллицы
- Резюме программы sed
- Послесловие
- Ссылки
HuMan: sed
Введение
Программа sed сложнее, чем те команды, что мы уже успели рассмотреть в предыдущих статьях цикла HuMan. В ее составе арсенал собственных команд, поэтому, дабы избежать тавтологии и путаницы, в этой статье команда sed впредь будет именоваться «программой» или «редактором», а команды редактора sed — просто командами.
Программа sed способна выполнять сложные задания, и нужно потратить время, чтобы научиться эти задания формулировать.
Но наряду со сложными действиями, у команды sed есть простые, но весьма полезные возможности, освоить которые не труднее, чем прочие команды Юникс. Не позволяйте себе из-за сложности освоения всей программы, отказываться от ее простых аспектов.
Мы начнем от простого к сложному, так что вы всегда сможете понять, где следует остановиться.
Команда s — substitution (замена)
Проще не бывает. А вот пример с вводом из файла zar.txt:
Я не брал выражение s/ОБРАЗЕЦ/ЗАМЕНУ/ в кавычки, так как данный пример не нуждается в кавычках, но если бы в нем присутствовали метасимволы, то кавычки были бы обязательны. Чтобы не ломать себе каждый раз голову, и не ошибиться ненароком, всегда ставьте кавычки, лучше более «сильные» одинарные, это хорошая привычка. Кашу маслом не испортишь. Я тоже во всех последующих примерах не буду манкировать кавычками.
Как мы видим, заменяющая команда s имеет четыре составляющих:
Прямой слэш (/) используется в качестве разделителя по традиции, так как предок программы sed — редактор ed использует их (как и редактор vi). В некоторых случаях такой разделитель весьма неудобен, например, когда надо менять пути (path) к директориям, которые тоже содержат прямой слэш (/usr/local/bin). В этом случае приходится разделять прямые слэши обратными:
Это называется «частокол» и выглядит весьма уродливо, а главное, непонятно.
Уникальность программы sed в том, что она позволяет использовать любой разделитель, например знак подчеркивания:
Если в поисках разделителя, который вам нравится, вы получаете сообщение «незавершенная команда `s'», значит этот символ не годится в качестве разделителя, или вы просто забыли поставить один-два разделителя.
В этой статье я вынужден использовать традиционный разделитель (/) чтобы не сбивать читателя с толку, но в случае необходимости стану использовать в качестве разделителя тильду (
Регулярные выражения (РВ)
Тема регулярных выражений настолько обширна, что ей посвящены целые книги (смотри ссылки в конце статьи). Тем не менее, говорить всерьез о редакторе sed, не применяя регулярных выражений, также непродуктивно, как разговаривать о тригонометрии при помощи счетных палочек. Поэтому необходимо рассказать хотя бы о тех регулярных выражениях, которые часто используются с программой sed.
с Или любая другая буква. Большинство букв, цифр и прочих неспециальных символов считаются регулярными выражениями, представляющими сами себя.
* Астериск, следующий за каким-либо символом или регулярным выражением, означает любое число (в том числе и нулевое) повторов этого символа или регулярного выражения.
\+ Означает один или более повтор символа или регулярного выражения.
\? Означает ни одного или один повтор.
\ Означает ровно i повторов.
\ Число повторов находится в интервале от i до j включительно.
\ Число повторов больше или равно i.
\ Число повторов меньше или равно j.
\(RE\) Запомнить регулярное выражение или его часть с целью дальнейшего использования как единое целое. Например, \(а-я\)* будет искать любое сочетание любого количества (в том числе и нулевого) строчных букв.
. Означает любой символ, кроме символа новой строки.
^ Означает нулевое выражение в начале строки. Другими словами, то, перед чем стоит этот знак, должно появляться в начале строки. Например, ^#include будет искать строки, начинающиеся с #include.
$ То же, что и предыдущее, только относится к концу строки.
[СПИСОК] Означает любой символ из СПИСКА. Например, [aeiou] будет искать любую английскую гласную букву.
[^СПИСОК] Означает любой символ, кроме тех, что в списке. Например, [^aeiou] будет искать любую согласную. Примечание: СПИСОК может быть интервалом, например [а-я], что будет означать любую строчную букву. Если нужно включить в СПИСОК ] (квадратную скобку) укажите ее в списке первой; если нужно включить в СПИСОК — (дефис), то укажите его в списке первым или последним.
RE1\|RE2 Означает РВ1 или РВ2.
RE1RE2 Означает объединение регулярных выражений РВ1 и РВ2.
\n Означает символ новой строки.
Внимание: Остальные условные обозначения на основе обратного слэша (\), принятые в языке С, не поддерживаются программой sed.
\1 \2 \3 \4 \5 \6 \7 \8 \9 Означает соответствующую по счету часть регулярного выражения, запомненную при помощи знаков \( и \).
abcdef Означает abcdef
a*b Означает ноль или любое количество букв а и одна буква b. Например, aaaaaab; ab; или b.
a\?b Означает b или ab
a\+b\+ Означает одну или больше букв а и одну или больше букв b. Например: ab; aaaab; abbbbb; или aaaaaabbbbbbb.
.* Означает все символы на строке, на всех строках, включая пустые.
.\+ Означает все символы на строке, но только на строках, содержащих хотя бы один символ. Пустые строки не соответствуют данному регулярному выражению.
^main.*(.*) Будет искать строки, начинающиеся со слова main, а также имеющие в своем составе открывающую и закрывающие скобки, причем перед и после открывающей скобки может находиться любое количество символов (а может и не находиться).
^# Будет искать строки, начинающиеся со знака # (например комментарии).
\\$ Будет искать строки, заканчивающиеся обратным слэшем (\).
[a-zA-Z_] Любые буквы или цифры
[^ ]\+ (В квадратной скобке, кроме символа ^, содержится еще пробел и табуляция) —Означает один или любое количество любых символов, кроме пробела и табуляции. Обычно имеется в виду слово.
^.*A.*$ Означает заглавную букву А точно в середине строки.
A.\<9\>$ Означает заглавную букву А, точно десятую по счету от конца строки.
^.\<,15\>A Означает заглавную букву А, точно шестнадцатую по счету от начала строки.
Теперь, когда мы познакомились с некоторыми регулярными выражениями, вернемся к команде s редактора sed.
Использование символа & когда ОБРАЗЕЦ неизвестен
Символ & (амперсанд), будучи помещен в состав ЗАМЕНЫ, означает любой найденный в тексте ОБРАЗЕЦ. Например:
Звездочка (астериск) после интервала 6 нужна чтобы заменены были все цифры, встретившиеся в образце. Без нее получилось бы:
То есть в качестве образца взята была первая же найденная цифра.
Вот пример со вполне осмысленной нагрузкой: составим файл formula.txt: и применим к нему команду:
Математическая формула приобрела однозначный смысл.
Еще символ амперсанда можно использовать для удвоения ОБРАЗЦА:
Тут есть одна тонкость. Если мы чуть усложним пример:
как и следовало ожидать, удваиваются только цифры, так как в ОБРАЗЦЕ нет букв. Но если мы поменяем части текста местами:
то никакого удвоения цифр не получится. Это особенность регулярного выражения 3* — оно ищет соответствия только в первом символе строки. Если мы хотим удвоения цифр, где бы они ни находились, нужно доработать регулярное выражение в ЗАМЕНЕ:
тогда цифры будут удваиваться, независимо от количества предшествующих «слов».
Использование условных знаков \(, \) и \1 для обработки части ОБРАЗЦА
Условные знаки \( и \) (escaped parentheses) применяются для запоминания части регулярного выражения.
Условный знак \1 означает первую запомненную часть, \2 — вторую, и так далее, вплоть до девяти запомненных частей (больше программа не поддерживает). Разберем пример:
Здесь \([a-z]*\) означает, что программа должна запомнить все буквенные символы в любом количестве; .* означает любое количество символов после первой запомненной части; а \1 означает , что мы хотим видеть только первую запомненную часть. Так и есть: в выводе программы мы видим только буквы и никаких цифр.
Для того, чтобы поменять слова местами, нужно запомнить два суб-ОБРАЗЦА, а потом поменять их местами:
Здесь \2 означает второй суб-ОБРАЗЕЦ, а \1 -первый. Обратите внимание на интервал между первым выражением \([а-я]*\) и вторым выражением \([а-я]*\). Он необходим, чтобы были найдены два слова.
Знак \1 вовсе не обязан быть только в ЗАМЕНЕ, он может присутствовать также и в ОБРАЗЦЕ, например, когда мы хотим удалить дубликаты слов:
Модификаторы замены команды s
Модификатор /g
Программа sed, как и большинство утилит Юникс, при работе с файлами считывают по одной строке. Если мы приказываем заменить слово, программа заменит только первое совпавшее с ОБРАЗЦОМ слово на данной строке. Если мы хотим изменить каждое слово, совпавшее с образцом, то следует ввести модификатор /g.
Без модификатора /g:
Редактор заменил только первое совпавшее слово.
А теперь с модификатором глобальной замены:
Все совпадения в данной строке были заменены.
А если нужно изменить все слова, скажем взять их в скобки? Тогда на помощь снова придут регулярные выражения. Чтобы выбрать все буквенные символы, как верхнего, так и нижнего регистра, можно воспользоваться конструкцией [А-Яа-я], но в нее не попадут такие слова как «что-то» или «с’езд». Гораздо удобнее конструкция [^ ]*, которая соответствует всем символам, кроме пробела. Итак:
Как выбрать нужное совпадение из нескольких
В этом примере мы запомнили оба слова, и, поставив второе (пингвин) на первое место, первое (глупый) удалили, поставив в секции ЗАМЕНЫ вместо него пробел. Если мы поставим вместо пробела какое-либо слово, то оно заменит первое (глупый):
Числовой модификатор
В этом примере каждое слово является совпадением, и мы указали редактору, какое по счету слово мы хотим заменить, поставив модификатор 2 после секции ЗАМЕНЫ.
Можно комбинировать цифровой модификатор с модификатором /g. Если нужно оставить неизменным первое слово, а второе и последующие заменить на слово «(удалено)», то команда будет такая:
Если нужно действительно удалить все последующие совпадения, кроме первого, то в секции ЗАМЕНЫ следует поставить пробел:
Или вовсе ничего не ставить:
Числовой модификатор может быть любым целым числом от 1 до 512. Например, если нужно поставить двоеточие после 80 символа каждой строки, то поможет команда:
Модификатор /p — выдавать на стандартный выход (печатать — print)
Программа sed и так по умолчанию выдает результат на стандартный выход (например экран монитора). Этот модификатор применяется только с опцией sed -n, которая как раз блокирует вывод результата на экран.
Модификатор /w
Модификатор /e (расширение GNU)
Модификаторы /I и /i (расширение GNU)
Комбинации модификаторов
Условные обозначения (расширение GNU)
- \L переводит символы ЗАМЕНЫ в нижний регистр
- \l переводит следующий символ ЗАМЕНЫ в нижний регистр
- \U переводит символы ЗАМЕНЫ в верхний регистр
- \u переводит следующий символ ЗАМЕНЫ в верхний регистр
- \E отменяет перевод, начатый \L или \U
По очевидным причинам эти условные обозначения применяются по одиночке. Например:
Мы рассмотрели почти все аспекты команды s редактора sed. Теперь настала очередь рассмотреть опции этой программы.
Опции программы sed
Опция -e
Один из способов выполнения нескольких команд — применение опции -e. Например:
Все предыдущие примеры в этой статье не требовали применения опции -e только потому, что содержали одну команду. Мы могли поставить в примерах опцию -e, это ничего бы не изменило.
Опция -f
Sedscript здесь — имя файла, содержащего команды. Этот файл называется скриптом программы sed (далее просто скрипт). Каждая команда скрипта должна занимать отдельную строку. Например:
Назвать скрипт можно как угодно, важно не путать файл скрипта с обрабатываемым файлом.
Опция -n
Так как совпадений с ОБРАЗЦОМ не найдено (в файле нет цифр), то команда s с модификатором /p и знаком & в качестве ЗАМЕНЫ (напомню, что амперсанд означает сам ОБРАЗЕЦ), работает как команда cat.
Если ОБРАЗЕЦ будет найден в файле, то строки, содержащие ОБРАЗЕЦ, будут удвоены:
Теперь добавим опцию -n:
Теперь наша программа работает как команда grep — возвращает только строки, содержащие ОБРАЗЕЦ.
Выбор нужных элементов редактируемого текста
- Выбирать строки по номерам
- Выбирать строки в некотором диапазоне номеров
- Выбирать только строки, содержащие некое выражение
- Выбирать только строки между некоторыми выражениями
- Выбирать только строки от начала файла и до некоторого выражения
- Выбирать только строки от некоторого выражения и до конца файла
Программа sed умеет все это и даже больше. Любая команда редактора sed может применяться адресно, в некотором диапазоне адресов, или с вышеперечисленными ограничениями круга строк. Адрес или ограничение должны непосредственно предшествовать команде:
Выбор строк по номерам
Выбор строк в диапазоне номеров
Если нужно указать диапазон до последней строки файла, а вы не знаете, сколько в нем строк, то воспользуйтесь знаком $:
Выбор строк, содержащих некое выражение
Выбор строк в диапазоне между двумя выражениями
Выбор строк от начала файла и до некоего выражения
Выбор строк от некоего выражения и до конца файла
Другие команды редактора sed
Команда d (delete)
Причем чаще пишут проще (без пробела):
Все, что было сказано в предыдущем разделе о адресации строк, справедливо и для команды d (как и для почти всех команд редактора sed).
При помощи команды d удобно выбросить ненужную «шапку» какого-нибудь почтового сообщения:
(Удалить строки с первой и до первой пустой строки).
Избавится от комментариев в конфигурационном файле:
И мало ли, где нужно удалить лишние строчки!
Команда p (print)
Будучи примененной сама по себе, команда p удваивает строки в выводе (ведь программа sed по умолчанию выводит строку на экран, а команда p выводит ту же строку вторично).
Этому свойству находится применение, например удвоить пустые строки для улучшения вида текста:
Но истинное свое лицо команда p раскрывает в сочетании с опцией -n, которая, как вы помните, запрещает вывод строк на экран. Комбинируя опцию -n с командой p, можно получить в выводе только нужные строки.
Например, просмотреть строки с первой по десятую:
Или только комментарии:
Что весьма напоминает работу программы grep, с чем мы уже сталкивались, когда говорили об опции -n с модификатором /p. Но, в отличие от команды grep, редактор sed дает возможность не только найти эти строки, но и изменить их, заменив, например, везде Linux на Unix:
Команда !
Или выберем все строки, кроме комментариев, из файла /boot/grub/menu.lst:
Команда q (quit)
Эта команда закончит работу по достижению 11-й строки.
Команда q — одна из немногих команд sed, не принимающих диапазонов строк. Не может же команда прекратить работу 10 раз подряд, если мы введем: Абсурд!
Команда w (write)
Мы получим файл gum.txt, содержащий две последние строки четверостишия Гумилева из файла gumilev.txt. Причем, если такой файл уже существует, то будет перезаписан. Если не ввести опцию -n, то программа, кроме создания файла gum.txt, еще и выведет на экран все содержание файла gumilev.txt.
Для работы в командной строке, удобнее пользоваться обычным перенаправлением вывода (> или >>), но в sed скриптах, вероятно, команда w найдет свое применение.
Команда r (read)
Команда =
Команда принимает только один адрес, не принимает интервалов.
Команда y
Команда y работает, только если количество символов в ОБРАЗЦЕ равно количеству символов в ЗАМЕНЕ.
Скрипты программы sed
Эта статья не может вместить описания скриптов sed, как и ее автор не ставит себе задачу освоение языка программирования sed. В этой статье я делал акцент на использование редактора sed в командной строке, имея прицел на использование его в качестве фильтра в программных каналах (pipes). По этой причине я опустил многочисленные команды sed, применяющиеся только в его скриптах.
Существует множество любителей редактора sed, и множество статей на тему скриптописания, в том числе и в Рунете. Так что для заинтересовавшихся этой замечательной программой не составит труда пополнить свои знания.
Программа sed и символы кириллицы
Резюме программы sed
Для освоения программы sed в полном объеме потребуются недели или даже месяцы работы, так как для этого необходимо:
Изучить регулярные выражения
С другой стороны, освоить несколько наиболее употребительных команд редактора sed не сложнее, чем любую команду Юникс; надеюсь, данная статья поможет вам в этом.
Послесловие
Данная статья является исключением, так как не описывает всех возможностей программы. Для полного их описания потребовалась бы не статья, а книга. Тем не менее, статья позволяет получить представление о редакторе sed и начать работать с этой удивительной программой, используя наиболее употребительные ее команды.
Ссылки
- А.Соловьев, SED и AWK (учебное пособие) . (Копия здесь )
- О.В.Галина, «Неинтерактивный текстовый редактор SED»
- Сергей Майков, Tips от Madskull’a: sed
Книги по регулярным выражениям:
- Фридл, Дж., «Регулярные выражения» , СПб., Издательство «Питер», 2001. 352 с. (Библиотека программиста).
- Смит, Билл. «Методы и алгоритмы вычислений на строках (regexp) — Computing Patterns in Strings. М., Издательство «Вильямс», 2006. 496 с.
- Форта, Бен. Освой самостоятельно регулярные выражения. 10 минут на урок М. Издательство «Вильямс», 2005. 184 с.
Источник