[без адреса]
Символ '#' служит для обозначения комментария. Комментарий длится от символа "#", и до конца строки. Для переносимости, самый первый символ скрипта может быть "#".
#!/bin/sed -rfпосле чего, я могу запускать свои скрипты, как обычные команды (./my_sed_script во время отладки, а перенеся их в /usr/local/bin/, просто набрав my_sed_script). Оболочка сама определяет, что это sed-скрипт и выполняет его. Таким скриптом можно пользоваться как и обычной sed, например:
$ cat input.txt | my_sed_script > output.txtя вывожу в stdout входной файл(input.txt), он обрабатывается моим скриптом, и записывается в output.txt
$ my_sed_script input.txt > output.txtтоже самое, что и в п1, просто тут сам скрипт читает файлы
$ my_sed_script test.txt -i.bakРедактирование "на месте", отредактированный файл записывается ВМЕСТО test.txt, при этом, старый файл сохраняется под именем "test.txt.bak".
$ my_sed_script *.html -ibackup_dir/*В данном случае, оболочка выдаёт моему скрипту все html файлы, которые скрипт последовательно обрабатывает(каждый отдельно, см. описание -i выше). При этом, старые файлы сохраняются в каталоге backu_dir(если он есть и доступен).
Эта команда принимает только один адрес.
Прерывание работы скрипта. Если не запрещён автоматический вывод буфера (без опции -n), буфер выводится в выходной поток. Можно дополнительно задать код завершения (EXIT-CODE). (это GNU расширение).
Удаляет содержимое буфера; после чего переходит к следующему циклу.
{ s/.*//; b }но при этом, ничего не выводится, все команды после d не выполняются. (потому сложно сказать, действительно-ли очищается буфер) конечно "sed '5d'" действительно отфильтрует пятую строку, но при этом, следует помнить, что не всё так просто... См. также.
Печать буфера (в stdout). Эту команду имеет смысл использовать только при использовании опции -n.
в моей версии sed применение этой команды без опции -n приводит к дублированию строк, в оригинале написано, что другие версии могут печатать только один раз, а стандарт POSIX трактует это как ошибку.
Потому в переносимых скриптах НЕ СЛЕДУЕТ использовать команду p без ключа -n (это касается так-же модификатора p команды s).
sed -n 'p;p'
Если авто-печать не отключена, печатает буфер, и затем заменяет содержимое буфера на следующую строку. Если авто-печать отключена (опция -n), то просто меняет содержимое буфера на следующую строку. Если следующей строки нет(текущая - последняя в тексте), то эта команда просто выводит содержимое буфера (если это разрешено), и работа скрипта завершается(следующие за n команды НЕ выполняются).
Группировка команд в блок. Вы можете использовать такие блоки, если хотите, что-бы некоторые команды выполнялись только для некоторых адресов(или диапазонов). Пример:
sed -n '3p;p'
эта команда будет просто печатать все строки, так-как 3p игнорируется для всех строк, однако, для третей строки команда 3p выполнится. (третья будет распечатана 2 раза).
sed -n '3{p;p}'
Ничего не распечатает, кроме третьей строки, которая выведется дважды.
Команда 's' является самой востребованной в sed-скриптах, это команда замены. Точнее будет сказать, это команда поиска, и(если найдено) замены. Синтаксис команды:
s/РЕГУЛЯРНОЕ_ВЫРАЖЕНИЕ/ВЫРАЖЕНИЕ_ДЛЯ_ЗАМЕНЫ/МОДИФИКАТОРЫ
Символ '/' разделяет части команды. Его можно поменять на любой другой символ. Если в РЕГУЛЯРНОМ_ВЫРАЖЕНИИ или в ВЫРАЖЕНИИ_ДЛЯ_ЗАМЕНЫ требуется использовать символ-разделитель('/' обычно), то его следует за экранировать.
Базовая концепция 's' проста: она ищет РЕГУЛЯРНОЕ_ВЫРАЖЕНИЕ, и, если его найдёт, заменяет найденное на ВЫРАЖЕНИЕ_ДЛЯ_ЗАМЕНЫ.
ВЫРАЖЕНИЕ_ДЛЯ_ЗАМЕНЫ может содержать `\N' (где N - цифра 1...9), эта "обратная ссылка" заменяется на подвыражение (в скобках) из РЕГУЛЯРНОЕ_ВЫРАЖЕНИЕ. Выражения нумеруются слева-направо. Если ВЫРАЖЕНИЕ_ДЛЯ_ЗАМЕНЫ содержит '&', то он заменяется на всю найденную строку.
Перед обратными ссылками(«\N» и «&») вы можете поставить префикс, один из \L
, \l
, \U
, \u
, или \E
. Впрочем, они работают для всего ВЫРАЖЕНИЯ_ДЛЯ_ЗАМЕНЫ Смысл этих префиксов:
\L
\U
или до \E
\l
\U
\L
или до \E
.\u
\E
\L
и \U
.Пример использования префиксов.
В оригинале написано, что «\», «&», и перевод строки останавливают замену, однако, у меня эти символы не останавливают конвертацию регистра.
$ echo "ABC XYZ" | sed -r 's/\<\w+\>/\L\u&/g' Abc XyzТут произошло две замены, и для каждой флаги преобразования регистра были установлены заново - сначала для найденного «ABC», а затем для «XYZ».
Для команды s предусмотрено множество МОДИФИКАТОРОВ:
g
НОМЕР
g
и НОМЕР
, GNU версия sed обрабатывает такую комбинацию сл. образом: Игнорируются все совпадения до совпадения НОМЕР
, а начиная с совпадения НОМЕР
все заменяются. Думаю нужны примеры в данном случае:
$ echo 'ABCDEFGH' | sed 's/./-/' -BCDEFGH # по умолчанию заменяется только первое вхождение РЕГУЛЯРНОГО_ВЫРАЖЕНИЯ $ echo 'ABCDEFGH' | sed 's/./+/g' ++++++++ # с МОДИФИКАТОРОМ g заменяются все вхождения $ echo 'ABCDEFGH' | sed 's/./+/4' ABC+EFGH # с МОДИФИКАТОРОМ НОМЕР заменяется только заданное вхождение(здесь - четвёртое) $ echo 'ABCDEFGH' | sed 's/./+/4g' ABC+++++ # комбинация МОДИФИКАТОРОВ 'g' и 'НОМЕР' # здесь заменились вхождения 4,5,6,7, и 8.
p
p
и e
, то от их порядка зависит результат. Например:
$ echo 'ABCDEFGH' | sed -n 's/.*/echo TEST/p' echo TEST # пример использования 'p' - простой вывод буфера. $ echo 'ABCDEFGH' | sed -n 's/.*/echo TEST/e' # МОДИФИКАТОР 'e' - команда выполняется, но её результат остаётся в буфере # возможна её дальнейшая обработка другими командами sed. Например: $ echo 'ABCDEFGH' | sed -n 's/.*/echo TEST/e;s/T/Q/p' QEST # первая команда 's' вывела в буфер слово TEST(при этом мы ничего не увидели), # а вторая команда заменила T на Q, и вывела буфер. $ echo 'ABCDEFGH' | sed -n 's/.*/echo TEST/ep' TEST # (МОДИФИКАТОР выполнить и распечатать), тут команда выполнилась, и мы видим результат # её работы. Обычно это и нужно. $ echo 'ABCDEFGH' | sed -n 's/.*/echo TEST/pe' echo TEST # (МОДИФИКАТОРЫ распечатать и выполнить) здесь сначала команда распечаталась, # а потом выполнилась. Результат её работы сохранён в буфере, для дальнейшей обработки. $ echo 'ABCDEFGH' | sed -n 's/.*/echo TEST/pep' sed: -e выражение #1, символ 18: несколько модификаторов `p' с командой `s' # а вот такое недопустимо. # если вы хотите распечатать-выполнить-распечатать, напишите `p' отдельной командой: $ echo 'ABCDEFGH' | sed -n 's/.*/echo TEST/pe;p' echo TEST TEST
pep
(который не поддерживается). Более правильным будет использование команды T после команды s///pe.
w FILE-NAME
/dev/stderr
, и /dev/stdout
.
e
МОДИФИКАТОРУ p
Команда завершается символом новой строки, если она завершается «\000», то результат работы не определён. Это расширение GNU.
I, i
M, m
Многие sed-скрипты используют только команду s, описанную в прошлой секции, однако, не стоит забывать, что sed умеет намного больше простой замены. Вот список часто используемых команд sed:
(в этой команде, при необходимости, разделитель «/» можно заменить на любой другой символ)
Эта команда заменяет символы из списка ЗАМЕНЯЕМЫЕ_СИМВОЛЫ, на символы из списка ЗАМЕНЯЮЩИЕ_СИМВОЛЫ. Списки должны быть одинаковой длинны (после де-экранирования).
y/ABC/XYZ/эта команда меняет «A» на «X», «B» на «Y», и «C» на «Z». Другие форматы не допускаются. Потому на sed невозможно написать классический "однострок на перле". Не думаю, что это большой минус. Хотя иногда приходится много кнопок давить :-(
Ну и как обычно, я впишу красненький «warning». Сама sed конечно не сможет исполнить «однострок на перле», однако, вы всё-же будьте внимательны...
Глюки и баги могут возникнуть и сами по себе, к примеру так.
В режиме «POSIXLY_CORRECT», эта команда имеет один адрес. В конце текущего цикла, в выходной поток добавляется TEXT. Как расширение GNU, можно писать:
$ echo 'ABCDEFGH' | sed -n 'a text1\ text2\ text3\ text4' text1 text2 text3 text4
как видите, символы «\» удаляются (как и в языке Си).
Это расширение так-же работает и в командах i и c.
$ echo 'ABCDEFGH' | sed 'a TEST' ABCDEFGH TEST $ echo 'ABCDEFGH' | sed 'i TEST' TEST ABCDEFGH $ echo 'ABCDEFGH' | sed 'c TEST' TEST $ echo 'ABCDEFGH' | sed '=' 1 ABCDEFGH
Вывод буфера в переносимой форме: непечатные символы(а так-же «\») выводится в Си-стиле (тремя восьмеричными цифрами, и перед ними добавляется «\») Длинные строки разрезаются, при резке в конец новых строк добавляется «\», Конец каждой строки помечается символом «$».
N определяет максимальный размер строки, если не задан, принимается значение заданное в командной строке ключом -l
, если и он не задан, N=70. Если N=0, строки не разбиваются. Параметр N - расширение GNU.
Эта команда читает файл FILENAME в конце текущего цикла (или перед чтение следующей строки), и выводит его содержимое в выходной поток. Если файл не удалось прочитать, или файл пустой, то ничего не происходит, и никаких сообщений об ошибке НЕ выводится. Пример:
$ cat z aaaaa # содержимое файла z $ echo 'ABCDEFGH' | sed 'r z s/./X/' XBCDEFGH aaaaa # сначала стоит команда r, а затем команда s, # однако мы видим, что sed выполняет команды не так, как мы их записали, # а в соответствии с этим документом: # СНАЧАЛА выполняется команда s, которая заменяет символ в буфере, # затем содержимое буфера выводится, # и лишь ПОСЛЕ этого, выполняется чтение и вывод файла (не думаю, что чтение # осуществляется ДО этого, в какую-то временную память).
В режиме «POSIXLY_CORRECT», эта команда имеет только один адрес.
Записывает буфер в FILENAME. См. так-же описание модификатора w
команды s.
Эта команда сначала создаёт файл (или, если уже есть, усекает его до нулевой длинны), а потому уже записывает. Если файл открыть не получилось, эта команда пытается его закрыть, и снова открыть. Если файл так и не открылся для записи, работа прерывается с сообщением об ошибке. Это так-же касается модификатора w
команды s.
Это совсем мутная команда, здесь кардинальным образом нарушается вся работа sed:
Таким образом, можно напихать в буфер множество строк, а после этого все это строки обработать по одной. Весь скрипт получается таким своеобразным циклом, который не слишком и удобен, по той причине, что точка входа в цикл всего одна, и совпадает с началом скрипта. Конечно, хотя точка входа единственная, точек выхода сколько угодно, и конечно эту команду всегда можно обойти.
s/^[^\n]*\n//См. также.
Добавляет новую строку из входного потока к буферу. Строки разделяются символом новой строки(\n). Если нет следующей строки, то работа sed завершается без выполнения оставшихся команд. Команда довольно мутная, поясню примером с прошлым файлом из двух строк:
$ sed 'N' 2l.txt line 1 second line # никаких изменений, файл никак не поменялся, # но это только с виду. # на самом деле, выполнился только один цикл работы sed, # сначала загрузилась первая строка (как обычно), а затем - вторая, # командой N, затем содержимое буфера вывелось на экран. # но так-как строки разделены \n, это выглядит как и оригинальный вывод (например # командой cat) $ sed 'N;s/\n/WWW/' 2l.txt line 1WWWsecond line # можно заменить \n в буфере на что-то другое, и тогда станет видно, что в # действительности это просто одна строка, хотя и с символом \n в середине.
Печать буфера сначала, и до первого символа \n.
Запись буфера в буфер2 (hold space).
Добавление буфера к буферу2. Например:
буфер: АБВ буфер2: ГДЕ после команды H: буфер: АБВ буфер2: ГДЕ\nАБВ
Замена содержимого буфера, на содержимое буфера2.
Добавляет к буферу содержимое буфера2. (вроде H, только меняется буфер).
Во многих случаях, используя следующие команды, вы можете избежать кодинга на других языках (вроде perl & awk), и решить задачи средствами самой sed.
In most cases, use of these commands indicates that you are probably better off programming in something like `awk' or Perl. But occasionally one is committed to sticking with `sed', and these commands can enable one to write quite convoluted scripts.
/X/ b lableосуществляется тогда, и только тогда, когда в буфере есть хотя-бы одна буква X. Многоуровневые, вложенные и обратные (в т.ч. циклы) переходы тоже работают.
# здесь какие-то sed команды, в том числе и команды замены # которые иногда заменяют, а иногда - нет. t label # переход к метке label, нет разницы, выполнится он или нет :label # потому-что метка label стоит сразу после команды перехода. s/ABC/&/ t found # преход выполнится только если будет найдено 'ABC'
Эти команды специфичны для GNU версии sed, вы можете использовать их в том, и только в том случае, если вы уверены, что ваши скрипты не понадобится запускать на других версиях sed.
e
).
-n
в тривиальных функциях.
$ sed 'R file1' file2выведет сначала первую строку файла2, потом первую строку файла1, затем вторую файла2 и т.д. Т.о. эта команда выведет оба файла, второй в нечётных, а первый в чётных строках результата.
$ sed -version GNU sed version 4.0.9 Copyright (C) 2003 Free Software Foundation, Inc. Эта программа - свободное программное обеспечение; условия её копирования смотрите в исходных текстах. Не предоставляется НИКАКИХ гарантий; даже подразумеваемых гарантий ПОЛЕЗНОСТИ или ПРИГОДНОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ, в той мере, в которой это может быть допущено законодательством. $ sed 'v 4.0' $ sed 'v 4.1' sed: -e выражение #1, символ 5: expected newer version of sedВот более современная версия:
$ sed -version GNU sed версия 4.2 Copyright (C) 2003 Free Software Foundation, Inc. Это свободное программное обеспечение; условия его копирования смотрите в исходных текстах. Не предоставляется НИКАКОЙ гарантии; даже гарантии ПРИГОДНОСТИ ДЛЯ ПРОДАЖИ или ПРИМЕНИМОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ, в той мере, в которой это может быть допущено законодательством. GNU sed home page: <http://www.gnu.org/software/sed/>. General help using GNU software: <http://www.gnu.org/gethelp/>. Отчеты об ошибках отправляйте по адресу: <bug-gnu-utils@gnu.org>. Убедитесь, что включили где-либо в поле ``Тема:'' слово ``sed''. $ sed 'v 4.2' ^C $ sed 'v 4.3' sed: -e выражение #1, символ 5: ожидалась более новая версия sed
sed 'W file2' file1Скопирует построчно файл1 в файл2.
(drBatty): В новейших версиях GNU sed появилась новая команда z, она очищает буфер. Однако, пока ещё в большинстве систем эта версия не установлена, и очищать приходится командой s/.*//, что во первых не работает если в буфере есть НЕСИМВОЛЫ, и во вторых теряется флаг для команд перехода.
Вы можете обсудить этот документ на форуме. Текст предоставляется по лицензии GNU Free Documentation License (Перевод лицензии GFDL).
Вы можете пожертвовать небольшую сумму яндекс-денег на счёт 41001666004238 для оплаты хостинга, интернета, и прочего. Это конечно добровольно, однако это намного улучшит данный документ (у меня будет больше времени для его улучшения). На самом деле, проект часто находится на грани закрытия, ибо никаких денег никогда не приносил, и приносить не будет. Вы можете мне помочь. Спасибо.