Потоковый редактор sed.

Сведения из теории

Регулярное выражение

Сводка флагов и команд

Контрольные задания

Литература

Сведения из теории.

Редактор sed происходит, непосредственно, от ed, поэтому вы легко его изучите и закрепите свои знания о редакторе ed.

Основа редактора sed проста:

sed 'список команд ed' имена_файлов┘

Читаются строки по одной из входных файлов; команды из списка применяются к каждой строке по одной в указанном порядке и результат редактирования записывается в стандартный выходной поток. Например, можно заменить в любом из указанных файлов строку UNIX на UNIX с помощью команды:

$ sed 's/UNIX/UNIX ≥/g' имена_файлов┘> выходной поток.

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

$ sed '┘' файл┘> файл - не лучшее решение; для замены содержимого файлов нужно задействовать временный файл или другую программу. В дальнейшем мы рассмотрим программу, реализующую задачу записи в существующий файл.

Редактор sed выдает все строки автоматически, поэтому команда p не нужна после ввода команды замены, приведенной выше; более того, если она задается, то каждая изменяемая строка печатается дважды. Однако кавычки необходимы почти всегда. Поскольку многие метасимволы программы sed имеют специальные значения и для интерпретатора. Рассмотрим, например, команду du -a, порождающую список имен файлов. Обычно она выдает размер и имя файла:

$ du -a ch4*

ch4.1

ch4.2

ch4.3

ch4.4

$

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

$ du -a ch4.*| sed 's/.*->//'

ch4.1

ch4.2

ch4.3

ch4.4

$

В команде удаляются все символы (.*) до крайнего правого символа табуляции включительно (он показан в шаблоне как ->). Аналогичным способом можно выделить из вывода команды who имена пользователей и время входа в систему:

$ who

lr tty1 Sep 29 07:14

ron tty3 Sep 29 10:31

you tty4 Sep 29 08:08

td tty5 Sep 29 09:20

$ who | sed 's/ .* / /'

lr 29 07:14

ron 29 10:31

you 29 08:08

td 29 09:20

$

Команда s заменяет пробелы и все, что следует за ним (максимально возможно, включая дополнительные пробелы) до следующего пробела на единственный пробел. Кавычки нужны.

Почти такую же команду sed можно использовать, чтобы создать программу getname, возвращающую имя пользователя:

$ cat getname

who am i | sed 's/ .*//'

$ getname

you

$

Другая команда sed применяется настолько часто, что ее можно поместить в командный файл с имеем ind. Эта команда вставляет пробелы до шага табуляции; она удобна для лучшего расположения текста при печати.

Реализовать команду ind просто: достаточно установить символ табуляции в начале каждой строки:

$ sed 's/^/ ->/'$* - I версия ind.

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

$ sed '/./s/^/ -> /' $ * - II версия ind.

Шаблон '././' задает любую строку, в которой есть по крайней мере один символ, кроме символа перевода строки, поэтому команда s не выполняется для пустых строк. Вспомним, что sed выдает все строки, независимо от того менялись они или нет, так, что пустые строки по-прежнему выдаются.

Есть еще один способ определения команды ind. Можно выполнять команды только для тех строк, которые не соответствуют данному шаблону, предварив команду знаком восклицания '!'. В команде

$ sed ' /^$/!s/^/ -> /' $* - III версия ind.

Шаблон /^$/ задает пустые строки (перевод строки сразу следует за ее началом), поэтому /^$/! Предписывает не выполнять команду для пустых строк.

Как уже отмечалось, sed печатает каждую строку автоматически, независимо от того, какие операции над ней выполнялись (если только она не была удалена). Кроме того, можно использовать большинство команд редактора ed. Поэтому легко составить программу sed, которая напечатает, скажем, 3 первых строки входного потока, а затем завершится:

$ sed 3q

$

Хотя 3q не является законной командой ed, для sed она имеет смысл: копировать строки и завершить выполнение после третьей.

От вас может потребоваться другая работа с данными, например вставка пробелов. Один из способов заключается в том, чтобы входной поток sed пропустить через команду ind, но поскольку редактор sed допускает несколько команд, можно сделать это путем одного обращения к sed (хотя и несколько необычно):

$ sed 's/^/ -> /

3q'

$

Обратите внимание, где находятся кавычки и символ перевода строки: команды должны быть на отдельных строках, но редактор игнорирует пробелы и символы табуляции в начале строки.

Представляется естественным с помощью рассмотренных выше примеров составить программу head, которая будет печатать несколько строк из каждого своего файла-аргумента. Но sed 3q (или 10q) настолько просто задать, что в этом никогда не возникало потребности. Однако мы ввели команду ind, так как соответствующая последовательность для sed длиннее. Четкого критерия в отношении того, когда имеет смысл создавать отдельную программу из сложной командной строки, нет, поэтому мы предлагаем вам свое решение: поместите программу в свой каталог /bin и посмотрите, будете ли вы ее действительно применять.

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

$ sed -f командный_файл

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

$ sed '/шаблон/q'

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

$ sed '/шаблон/d'

удаляет каждую строку, содержащую шаблон; удаление происходит до автоматического вывода строк, поэтому удаленные строки не учитываются.

Хотя автоматический вывод обычно удобен, иногда он мешает. Его можно отключить с помощью флага -n; в этом случае в выходном потоке появятся только строки, задаваемые явной командой вывода p. Например,

$ sed -n '/шаблон/p'

эквивалентен команде grep -v. Условие сопоставления можно инвертировать, если завершить его символом !, поэтому

$ sed -n '/шаблон/! p'

эквивалентно команде grep -v. (Так же, как sed '/шаблон/d'.)

Для чего нужны две команды sed и grep? В конце концов, grep - всего лишь частный случай команды sed. Это в какой-то степени объясняется историческими причинами: команда grep появилась намного раньше, чем команда sed. Но она не только уцелела, но и активно применялась. В силу специфики назначения обеих команд grep значительно проще использовать, чем команду sed, так как ее использование в типичных ситуациях настолько лаконично, настолько возможно (к тому же у нее есть возможности, отсутствующие у команды sed; например, описание флага -b). Но все-таки программы могут "умирать". Когда-то была программа с именем gres, выполняющая простую подстановку, но она исчезла почти мгновенно, когда появилась команда sed.

Используя запись, такую же, как в редакторе ed, можно вставлять символы перевода строк с помощью команды sed:

$ sed '/ $/\

> /'

Здесь добавляется символ перевода строки к каждой строке, и таким образом пустые строки вставляются во входной поток, а команда

$ sed 's [->] [->]*/\

>/g'

заменяет каждую последовательность пробелов или символов табуляции на символ перевода строки, т.е. разбивает входной поток на строки из одного слова. (Регулярное выражение '[->]' задает пробел или символ табуляции, '[->]*' задает нуль или более таких символов, а весь шаблон - один или более пробелов и/или символов табуляции.)

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

$ sed -n '20,30p' Печатать только строки с 20-й по 30-ю.

$ sed 'l,10d' Удаление строк с 1-й до 10-й (=tail +11).

$ sed 'l,/ $/,/ end/p' Удаление всех строк до первой пустой включительно.

$ sed '$d' Удаление последней строки.

Строки нумеруются с начала входного потока; обнуление не происходит с началом нового файла.

У команды sed есть существенное ограничение, которое, однако, отсутствует в редакторе ed: в ней поддерживается относительная нумерация строк. В частности, операции + и - не действуют в выражениях, задающих номера строк, поэтому невозможно двигаться назад во входном потоке:

$ sed '$-1d' Недопустима обратная адресация.

Unrecognized command: $-1d

$

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

$ sed '/что-то/+1d' Недопустима прямая адресация.

Редактор sed имеет возможность записывать в несколько выходных файлов. Например, команда

$ sed -n' /шаблон/w файл1

> /шаблон/! Файл2' имена_файлов┘

$

записывает строки, соответствующие "шаблон", в файл1, а не соответствующие - в файл2, или, если вернуться к нашему первому примеру:

$ sed 's/UNIX≥/gw u.out' имена_файлов┘> выход

то здесь, как и ранее, весь выходной поток записывается в файл "выход", но к тому же измененные строки записываются в файл u.out.

Иногда нужна помощь со стороны интерпретатора, чтобы в команду редактора включить аргументы командного файла. Одним из примеров служит программа newer, которая выдает все более новые, чем заданный, файлы каталога:

$cat newer

Nr. Newer f: список файлов, созданных после f

Ls -t | sed '/ '$l'$/q'

$

Кавычки защищают различные специальные символы, предназначенные для редактора, оставляя $1 открытым для интерпретатора, чтобы он заменил его на имя файла. Существует альтернативный способ записи аргумента:

"/^$1\ $/q"

так как $1 заменяется на аргумент, тогда как \$ становится просто $.

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

$ cat older

Nr. Older f: список файлов, созданных ранее f

Ls -tr | sed '/ '$l'$/q'

$

Единственное различие состоит в применении флага -r в команде ls для изменения порядка выдачи файлов.

Редактор sed удобен потому, что позволяет работать с произвольными входными строками. Это "быстрый" редактор, который сходен с редактором ed в интерпретации регулярных выражений и в обработке отдельных строк. Однако, с другой стороны его возможности запоминания ограничены (трудно запомнить текст от одной строки до другой) - делается только один проход по данным, нельзя двигаться назад, нет способов прямой адресации типа /┘/+1; и нет средств для работы с числами, т.е. он является чисто текстовым редактором.

Регулярное выражение.

- Регулярное выражение указывается в разделителях: "/ /".

- Любой символ (кроме специальных: \[.^*$) является регулярным выражением себя.

- Символ ^ в начале регулярного выражения указывает на пустой символ в начале регулярного выражения. (Т.е. на начало строки).

- Символ $ в конце регулярного выражения указывает на пустой символ в конце регулярного выражения. (Т.е. на конец строки).

- Символ \n обозначает новую строку (newline).

- Символ - обозначает любой символ (кроме обыкновенного newline );

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

- Выражение [ ] указывает на один из символов, приведенных внутри.

- Выражение [^ ] указывает на один из символов, кроме приведенных внутри.

- Символ \ перед любым символом, кроме цифр и "(" , ")" , означает этот символ. (Экранирование специальных символов).

- Выражение \(x\), где x - регулярное выражение, указывает на x.

- Символы \d, где d - цифра, указывает копию d-того выражения, которое заключалось в скобки "\(" и "\)"

- Конкатенация регулярных выражений является регулярным выражением.

 

Примеры регулярных выражений:

/alex/ - указывает на строки содержащие "alex" , "abcalexdef" ,...;

/al.*ex/ - указывает на строки, содержащие "alex" , alabcex" ,....;

/^[Aa]lex/ - на строки, начинающиеся с "Alex" или "alex";

/./ - попадают все строки, имеющие хотя бы 1 символ (не newline);

/\./ - попадают строки, содержащие ".";

/^[^ ]/ - строки, не начинающиеся с " ";

/\(al\).*\1/ - строки, содержащие два вхождения "al" не подряд.

Сводка флагов и команд.

Флаги.

1) -e script - В script задаются команды редактирования. Если задано несколько флагов , каждая строка обрабатывается сначала первым script, затем вторым и т.д. Если кроме задан флаг -f, то в начале команды, заданные в script, а затем - в sfile.

Пример: Найти в файле file строки, содержащие шаблон 2222 и удалить их.

Sed -e /2222/d file

2) -f - Выполняются команды редактирования, помещенные в файл sfile. Если задано несколько флагов -f, каждая строка обрабатывается сначала первым sfile, затем вторым и т.д.

Пример: Найти в файле file строки, содержащие шаблон 2222 и удалить их.

Тогда файл sfile будет иметь следующий вид:

/2222/d

 а комманда редактирования будет следующая:

Sed -f sfile file

3) -n - Выводятся только те строки, которые явно указаны коммандой редактора p.

Пример: Найти в файле file cтроку с шаблоном 2222 и вывести ее.

Sed -n '/2222/p' file

 

Комманды редактора.

Общий вид комманд редактора sed следующий:

[addr1[,addr2]]function[arg]

где

addr1, addr2 - адреса строк, на которые воздействует команда;

function - команда или группа команд, заклюяенных в символы '{' и '}';

arg - аргументы команды.

Принята сквозная нумерация строк по всем входным файлам. Первая строка первого файла имеет номер 1.

Для адрессации строк используются как десятичные числа - номера строк, так и контекстные адреса - регулярные выражения.

Областью регулярного выражения считаются все адресуемые им строки. Область регулярного выражения может быть расширена при использовании команды N.

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

Если перед командой не указан адрес, она применяется к каждой входной строке; если указан один адрес - ко всем отмеченным им строкам; если указаны два адреса - к заданным интервалам строк.

В приведенном списке команд в скобках указано максимально допустимое для данной команды колличество адресов. Команды с большим количеством адресов называются ошибочными.

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

 

Приведем сводку комманд редактора и для основных напишем примеры программ:

Пусть файл file имеет вид:

1111

2222

3333

4444


1) a\

text - Добавление текста text после указанной строки.

Пример:

Sed '1a\

Alex

' file

После выполнения этой комманды на экране мы увидим:

1111

Alex

2222

3333

4444


2) b label - Перейти на команду: label.

Пример:

sed '2a\

Alex

b lb

2d

: lb 3d

' file

Результат выполнения:

1111

2222

Alex

4444


3) c\

text - Замена строки или группы строк текстом text.

Пример:

Sed '2c\

Alex

' file

Результат выполнения:

1111

Alex

3333

4444


4) d - Удалить строку; прочесть следующую входную строку.

Пример:

Sed '2d

' file

Результат выполнения:

1111

3333

4444


5) i\

text - Вставка текста text перед указанной строкой.

Пример:

Sed '2i\

Alex

' file

Результат выполнения:

1111

Alex

2222

3333

4444


6) p - Выдать строки.

Пример:

Sed -n '3p

Alex

' file

Результат выполнения:

3333 


7) q - Выйти.

Пример:

Sed '

q

' file

Результат выполнения:

1111


8) s/old/new/f - Заменить old на new. Если f=g, заменить все вхождения; f=p, выход; f=w файл, записать файл.

Пример:

Sed 's/1111/alex/g' file

Результат выполнения:

Alex

2222

3333

4444 


9) t label - Проверка: переход на метку, если была замена в текущей строке.

Пример:

Sed '1c\

Alex

T out

:out

' file

Результат выполнения:

1111

Alex

3333

4444


10) w file - Записать строку в файл.

Пример:

Sed '/1111/w temp' file

Результат выполнения:

Cat temp

1111


11) y/str1/str2/ - Заменить каждый символ строки str1 на соответствующий символ строки str2.

Пример:

Sed 'y/1234/4321/' file

Результат выполнения:

4111

3222

2333

1444


12) = - Выдать текущую нумерацию входной строки.

Пример:

Sed '=' file

Результат выполнения:

1

1111

2

2222

3

3333

4

4444


13) !cmd - Выполнить команду sed cmd, только если строка не выбрана.

Пример:

sed '2,4!d' file

Результат выолнения:

2222

3333

4444


14) !function - Выполнение команд function над строками, не указанными адресной частью команды.

15) :label - Установить метку для команды b и t.

16) { - Команды до соответствующей скобки } рассматривать как группу.

17) # - Комментарий. Если '#' является первым символом в строке, строка не выполняется, а рассматривается как комментарий.

18) r file - Читать file, содержимое его переслать в выходной поток после указанной строки.

19) n - Чтение следующей входной строки. Текущая строка выводится, но выполнение программы редактирования продолжается со следующей команды.

20) l - Выдать строку, напечатав все невидимые символы.

21) D - Удаление до первого символа перевода строки в области регулярного выражения.

22) g - Копирование содержимого буфера хранения в область регулярного выражения.

23) G - Добавление содержимого буфера хранения в область регулярного выражения.

24) h - Копирование содержимого области регулярного выражения в буфер хранения.

25) H - Добавление содержимого области регулярного выражения в буфер хранения.

26) N - Добавление следующей входной строки к текущей области регулярного выражения. Строки разделяются экранированным символом перевода строки.

27) P - Вывод до первого символа перевода строки (включительно) в области регулярного выражения.

28) x - Обмен содержимым буфера хранения в области регулярного выражения.

Контрольные задания.

Задания

Ответы

Найти в файле file строки, содержащие шаблон '2222', и удалить их.

Sed '/2222/d' file

Подсчитать количество строк в файле file.

Sed -n '$=' file

Раскидать строки, содержащие шаблон '1' в файл с именем 1str, шаблон '2' - в файл 2str, шаблон '3' - в файл 3str, шаблон '4' - в файл 4str.

Sed -n '

/1/w 1str

/2/w 2str

/3/w 3str

/4/w 4str

' file

Закодировать текст. Алфавит: abcdefgh, соответствующий код: 12345678 (т.е. a=1, b=2,..,h=8).

Sed 'y/abcdefgh/12345678/' file

 

Найти в файле file строку по шаблону '2222' и заменить ее на строку Alex.

Sed '/2222/c\

Alex

' file

Литература:

1. Керниган Б.В., Пайк Р. "Unix. Универсальная среда программирования."

2. Беляков М.И., Рабовер Ю.И., Фридман А.Л. "Мобильная операционная система"

Также вы можете получить информацию по следующим адресам:

http://citforum.perm.ru/operating_systems/articles/sed_awk.shtml

http://citforum.perm.ru/operating_systems/articles/tut_6.shtml

Данный документ создан 12.1998 студентом ПГТУ ЭТФ гр. АСУ-96-1 Коновкиным А.В.