Скрипты sed & awk

Автор Babay, 14 февраля 2012, 08:55:40

« назад - далее »

0 Пользователи и 3 гостей просматривают эту тему.

Malaheenee

Цитата: Babay от 02 марта 2012, 12:24:32вордовские файлы, на самом деле, состоят из 2-х - по-моему - сам текст (txt) и оформление (XML).
Это docx, как мы помним.
А doc - это бинарный проприетарный формат. Тут perl нужен (xls мы читаем и пишем через perl).
Все мы где-то, когда-то и в чем-то были новичками.

ihammers

Открыть содержимое (спойлер)
ЦитироватьНе увлекайтесь оверквотингом. Malaheenee
Так я и не увлекаюсь, насколько я помню я запихал данный ответ в спойлер.
[свернуть]
А если по теме, то самый удачный вариант был бы если информация из базы тянулась.  А построение было бы через xml.

PS: а так стоит глядеть в сторону perl или других языков.
Debian GNU/Linux Bookworm, LXQt/OpenBox: AMD Ryzen 5 5600G / 64Gb RAM
_______________________________
Debian GNU/Linux Bookworm, без графики: AMD Phenon X4 / 16Gb RAM
_______________________________
Debian GNU/Linux Bookworm, LXQt/OpenBox: Acer Aspire One 722 AMD C60 / 8Gb RAM / ATI HD6290

Babay

Значит Perl - наше ВСЕ!  :)
Ин дер гроссе фамилиен нихт клювен клац-клац...

Malaheenee

Открыть содержимое (спойлер)
ihammers, спойлер был. Но вроде как принято убирать только оффтоп под спойлер, а не ответ по теме  ;)
[свернуть]
Все мы где-то, когда-то и в чем-то были новичками.

ihammers

Открыть содержимое (спойлер)
Цитата: Malaheenee от 02 марта 2012, 13:10:26
Открыть содержимое (спойлер)
ihammers, спойлер был. Но вроде как принято убирать только оффтоп под спойлер, а не ответ по теме  ;)
[свернуть]
Malaheenee, по мне так это был практически оффтом, так как нет прямого ответа на поставленный вопрос, а имеется лишь рассуждения ;).  Думаю стоит закончить полемику и вернуться к вопросу скриптов, в частности сведением таблиц с помощью sed & awk.
[свернуть]
Debian GNU/Linux Bookworm, LXQt/OpenBox: AMD Ryzen 5 5600G / 64Gb RAM
_______________________________
Debian GNU/Linux Bookworm, без графики: AMD Phenon X4 / 16Gb RAM
_______________________________
Debian GNU/Linux Bookworm, LXQt/OpenBox: Acer Aspire One 722 AMD C60 / 8Gb RAM / ATI HD6290

orlyanuch

Выше приводил ссылку на полезные однострочные скрипты sed.
Но она от времени может сдохнуть, поэтому пусть здесь тоже будет, под спойлером.

Открыть содержимое (спойлер)
Пространство между строками:

    * Двойное пространство между строками:
    sed G
    * Двойное пространство между строками исключая пустые строки (на выходе содержатся не больше одной пустой строки между двумя строками с текстом):
    sed '/^$/d;G'
    * Тройное пространство между строками:
    sed 'G;G'
    * Удалить каждую вторую строку:
    sed 'n;d'
    * Вставить пустую строку перед каждой строкой соответствующей регулярному выражению "regex":
    sed '/regex/{x;p;x;}'
    * Вставить пустую строку после каждой строки соответствующей регулярному выражению "regex":
    sed '/regex/G'
    * Вставить пустую строку перед и после каждой строки соответствующей регулярному выражению "regex":
    sed '/regex/{x;p;x;G;}'

Нумерация:

    * Нумерация каждой стоки в файле filename. Используя отступ (tab) (смотрите примечание по '\t' в конце документа) вместо пустой строки:
    sed = filename | sed 'N;s/\n/\t/'
    * Нумерация каждой строки в файле filename (номер слева, выравненый по правому краю):
    sed = filename | sed 'N; s/^/ /; s/ *\(.\{6,\}\)\n/\1 /'
    * Нумерация каждой строки в файле filename, с выводом номера только для не пустых строк:
    sed '/./=' filename | sed '/./N; s/\n/ /'
    * Подсчет строк (эмуляция "wc -l"):
    sed -n '$='

Преобразование и замена текста:

    * В UNIX окружении: преобразование окончания строк из формата DOS (CR/LF) в формат Unix (LF):
    sed 's/.$//' (подразумевается что все строки заканчиваются с CR/LF)
    sed 's/^M$//' (в bash/tcsh, нажмите Ctrl-V затем Ctrl-M)
    sed 's/\x0D$//' (работает в ssed, gsed 3.02.80 или выше)
    * В UNIX окружении: преобразование разрыва строк Unix (LF) в формат DOS:
    sed "s/$/`echo -e \\\r`/" (команда в ksh)
    sed 's/$'"/`echo \\\r`/" (команда под bash)
    sed "s/$/`echo \\\r`/" (команда под zsh)
    sed 's/$/\r/' (команда под gsed 3.02.80 или выше)
    * В DOS окружении: преобразование разрыва строк Unix (LF) в формат DOS:
    Версия 1: sed "s/$//"
    Версия 2: sed -n p
    * В DOS окружении: преобразование разрыва строк DOS (CR/LF) в формат Unix. Работоет только с sed версии 4.0.7 или выше. Версию в Unix окружении можно узнать, вызвав SED с параметром "--version". В версии ниже, в DOS окружении такой фокус не пройдет. Использвйте взамен комманду "tr":
    sed "s/\r//" infile >outfile (sed v4.0.7 или выше)
    tr -d \r <infile >outfile (GNU tr версии 1.22 или выше)
    * Удалить все пробелы и символы табуляции в начале каждой строки файла (смотрите примечание по табуляции в конце документа):
    sed 's/^[ \t]*//'
    * Удалить все пробелы и символы табуляции в конце каждой строки файла (смотрите примечание по табуляции в конце документа):
    sed 's/[ \t]*$//'
    * Удалить все пробелы и символы табуляции в начале и конце каждой строки файла (смотрите примечание по табуляции в конце документа):
    sed 's/^[ \t]*//;s/[ \t]*$//'
    * Вставить 5 пробелов в начале каждой строки (создать смещение страницы):
    sed 's/^/ /'
    * Расположить весь текст по правому краю столбца шириной в 79 символов:
    sed -e :a -e 's/^.\{1,78\}$/ &/;ta' (устанавливает как 78 плюс 1 пробельный символ)
    * Центрировать весь текст посередине столбца шириной 79 символов. В версии 1, пробелы добовляются в начало и конец строки. В версии 2, пробелы добовляются только в начало строки:
    Версия 1: sed -e :a -e 's/^.\{1,77\}$/ & /;ta'
    Версия 2: sed -e :a -e 's/^.\{1,77\}$/ &/;ta' -e 's/\( *\)\1/\1/'
    * Поиск и замеа "foo" на "bar" в каждой строке:
    sed 's/foo/bar/' (замена только первого совпадения в строке)
    sed 's/foo/bar/4' (замена первых 4рех совпадений в строке)
    sed 's/foo/bar/g' (замена ВСЕХ совпадений в строке)
    sed 's/\(.*\)foo\(.*foo\)/\1bar\2/' (замена предпоследнего совпадения)
    sed 's/\(.*\)foo/\1bar/' (замена только последнего совпадения)
    * Замена "foo" на "bar" ТОЛЬКО для строк содержащих "baz":
    sed '/baz/s/foo/bar/g'
    * Замена "foo" на "bar" ИСКЛЮЧАЯ строки содержащие "baz":
    sed '/baz/!s/foo/bar/g'
    * Замена "scarlet" или "ruby", или "puce" на "red":
    sed 's/scarlet/red/g;s/ruby/red/g;s/puce/red/g' (большинство sed-ов)
    gsed 's/scarlet\|ruby\|puce/red/g' (только GNU sed)
    * Перевернуть последовательность строк (эмуляция "tac") (ошибка/особеннось в HHsed v1.5 причина удалению пустой строки):
    Версия 1: sed '1!G;h;$!d'
    Версия 2: sed -n '1!G;h;$p'
    * Перевернуть каждую строку в файле задом наперед (эмуляция "rev"):
    sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//'
    * Соеденить каждую пару строк бок о бок (подобно "paste"):
    sed '$!N;s/\n/ /'
    * Если линия заканчивается обратной косой чертой "\", то присоеденить следующую линию:
    sed -e :a -e '/\\$/N; s/\\\n//; ta'
    * Если линия начинается с знака "=", то присоеденить ее к предыдущей линии и заменить "=" пробелом:
    sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D'  для разбора команды: sed -n '$!N;s/\n=/ /;l;=;P;D;'
    * Добавить запятые к строке из чисел, изменяя "1234567" на "1,234,567":
    gsed ':a;s/\B[0-9]\{3\}\>/,&/;ta' (GNU sed)
    sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta' (другие sed-ы)
    * Добавить запятые к числу с десятичной частью и знаком минуса (GNU sed):
    gsed -r ':a;s/(^|[^0-9.])([0-9]+)([0-9]{3})/\1\2,\3/g;ta'
    * Добавить пустую строку через каждые 5 строк (после строк 5, 10, 15, 20, и т.д.):
    gsed '0~5G' (только GNU sed)
    sed 'n;n;n;n;G;' (другие sed-ы)

Выборочная печать некоторых строк:

    * Печатать первые 10 линий файла (эмуляция "head"):
    sed 10q
    * Печатать первую строку файла (эмуляция "head -1"):
    sed q
    * Печатать последние 10 строк файла (эмуляция "tail"):
    sed -e :a -e '$q;N;11,$D;ba'
    * Печатать последние 2 строки файла (эмуляция "tail -2"):
    sed '$!N;$!D'
    * Печатать последнюю строку файла (эмуляция "tail -1"):
    Версия 1: sed '$!d'
    Версия 2: sed -n '$p'
    * Печатать предпоследнюю строку в файле:
    sed -e '$!{h;d;}' -e x (для однострочного файла печатать пустую строку)
    sed -e '1{$q;}' -e '$!{h;d;}' -e x (для однострочного файла печатать эту строку)
    sed -e '1{$d;}' -e '$!{h;d;}' -e x (для однострочного файла ничего не печатать)
    * Печатать только те строки, которые совпадают с регулярным выражением (эмуляция "grep"):
    Версия 1: sed -n '/regexp/p'
    Версия 2: sed '/regexp/!d'
    * Печатать только те строки, которые НЕ совпадают с регулярным выражением (эмуляция "grep -v"):
    sed -n '/regexp/!p' - Версия 1, corresponds to above
    sed '/regexp/d' - Версия 2, simpler syntax
    * Печатать строку непосредственно перед регулярным выражением, но не печатать строку содержащую регулярное выражение:
    sed -n '/regexp/{g;1!p;};h'
    * Печатать строку непосредственно после регулярного выражения, но не печатать строку содержащую регулярное выражение:
    sed -n '/regexp/{n;p;}'
    * Печатать по одной строке перед и после регулярного выражения, с указанием номера строки совпадающей с регулярным выражением (симуляция "grep -A1 -B1"):
    sed -n -e '/regexp/{=;x;1!p;g;$!N;p;D;}' -e h
    * Печать строк, совпадающих с регулярными выражениями AAA, BBB и CCC одновременно (в любой последовательности):
    sed '/AAA/!d; /BBB/!d; /CCC/!d'
    * Печать строк, совпадающих с регулярными выражениями AAA, BBB и CCC одновременно (в конкретной последовательности):
    sed '/AAA.*BBB.*CCC/!d'
    * Печать строк, совпадающих с любым регулярным выражением AAA или BBB, или CCC (эмуляция "egrep"):
    sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d (большинство sed'ов)
    gsed '/AAA\|BBB\|CCC/!d' (только GNU sed)
    * Печатать абзац если он содержит AAA (пустая строка разделяет абзацы) (в HHsed v1.5 необходимо вставить 'G;' после 'x;'):
    sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;'
    * Печатать абзац если он содержит AAA, BBB и CCC (в любой последовательности) (в HHsed v1.5 необходимо вставить 'G;' после 'x;'):
    sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;/BBB/!d;/CCC/!d'
    * Печатать абзац если он содержит AAA или BBB, или CCC (в HHsed v1.5 необходимо вставить 'G;' после 'x;'):
    sed -e '/./{H;$!d;}' -e 'x;/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d
    gsed '/./{H;$!d;};x;/AAA\|BBB\|CCC/b;d' (только GNU sed)
    * Печатать строки длиной равной или большей 65 символов:
    sed -n '/^.\{65\}/p'
    * Печатать строки длиной меньше или равной 65 символов:
    sed -n '/^.\{65\}/!p' - Версия 1, отвечает условию
    sed '/^.\{65\}/d' - Версия 2, более простой синтаксис
    * Печатать часть файла начиная от совпадения с регулярным выражением и до конца файла:
    sed -n '/regexp/,$p'
    * Печатать часть файла основываясь на номерах строк (строки 8-12, включительно):
    Версия 1: sed -n '8,12p'
    Версия 2: sed '8,12!d'
    * Печатать строку под номером 52:
    sed -n '52p' - Версия 1
    sed '52!d' - Версия 2
    sed '52q;d' - Версия 3, эффективен на больших файлах
    * Начиная с 3ей строки печатать каждую седьмую строку в файле:
    gsed -n '3~7p' (только GNU sed)
    sed -n '3,${p;n;n;n;n;n;n;}' (другие sed-ы)
    * Печатать часть файла между двумя регулярными выражениями (включительно):
    sed -n '/Iowa/,/Montana/p' (регистро зависимый)

Избирательное удаление определенных строк:

    * Печатать все линии ИСКЛЮЧАЯ часть между двумя регулярными выражениями:
    sed '/Iowa/,/Montana/d'
    * Удалить дубликаты последовательных строк в файле (эмуляция "uniq"). Первая строка в наборе дубликатах строк удерживается от удаления:
    sed '$!N; /^\(.*\)\n\1$/!P; D'
    * Удалить дубликаты непоследовательных строк в файле. Остерегайтесь переполнения буфера или используйте GNU sed:
    sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P'
    * Печатать только дубликаты строк (эмуляция "uniq -d"):
    sed '$!N; s/^\(.*\)\n\1$/\1/; t; D'
    * Удалить первые 10 строк в файле:
    sed '1,10d'
    * Удалить последнюю строку в файле:
    sed '$d'
    * Удалить 2 последние строки файла:
    sed 'N;$!P;$!D;$d'
    * Удалить последние 10 строк файла:
    Версия 1: sed -e :a -e '$d;N;2,10ba' -e 'P;D'
    Версия 2: sed -n -e :a -e '1,10!{P;N;D;};N;ba'
    * Удалить каждую восьмую строку в файле:
    gsed '0~8d' (только GNU sed)
    sed 'n;n;n;n;n;n;n;d;' (другие sed-ы)
    * Удалить строки совпадающие с регулярным выражением:
    sed '/pattern/d'
    * Удалить ВСЕ пустрые строки из файла (эмуляция "grep '.' "):
    Версия 1: sed '/^$/d'
    Версия 2: sed '/./!d'
    * Удалить все последовательности пустых строк из файла исключая первую. Также удалить все пустые строки в начале и в конце файла (эмуляция "cat -s"):
    sed '/./,/^$/!d' (Версия 1, допускается 0 пустых строк в начале и 1 в конце файла)
    sed '/^$/N;/\n$/D' (Версия 2, допускается 1 пустая строка в начале и 0 в конце файла)
    * Оставить последовательность пустых строк не более двух одновременно:
    sed '/^$/N;/\n$/N;//D'
    * Удалить все пустые строки в начале файла:
    sed '/./,$!d'
    * Удалить все пустые строки в конце файла:
    sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' (для всех sed-ов)
    sed -e :a -e '/^\n*$/N;/\n$/ba' (для всех, кроме gsed 3.02.*)
    * Удалить последнюю непустую строку в каждом абзаце:
    sed -n '/^$/{p;h;};/./{x;/./p;}'

Специальные приложения:

    * Получить заголовок Usenet/e-mail сообщения:
    sed '/^$/q' (удаляет все после первой пустой строки)
    * Получить тело Usenet/e-mail сообщений:
    sed '1,/^$/d' (удаляет все до первой пустой строки)
    * Получить заголовок Subject (тема Usenet/e-mail сообщения), без удаления части "Subject: ":
    sed '/^Subject: */!d; s///;q'
    * Получить заголовок обратный адрес:
    sed '/^Reply-To:/q; /^From:/h; /./d;g;q'
    * Анализировать правильный исходящий адрес. # Pulls out the e-mail address by itself from the 1-line return address header (see preceding script):
    sed 's/ *(.*)//; s/>.*//; s/.*[:<] *//'
    * Добавить скобку и пробел в начало каждой строки (цитирование сообщения):
    sed 's/^/> /'
    * Удалить скобку и пробел в начале каждой строки (unquote a message):
    sed 's/^> //'
    * Удалить большинство HTML тегов (включая теги состоящие из несколько строк):
    sed -e :a -e 's/<[^>]*>//g;/</N;//ba'
    * Извлечение закодированных (uuencoded) двоичных данных из нескольких частей, удаление внешней заголовочной информации. Итак это только часть закодированного остатка. Файлы пропущенные через sed должны быть пропущены в правильной последовательности. Версия 1 может быть введена из командной строки, версия 2 может быть встроена в исполняемый скрипт оболочки Unix. (Модифицированна из скрипта Rahul Dhesi):
    Версия 1: sed '/^end/,/^begin/d' file1 file2 ... fileX | uudecode
    Версия 2: sed '/^end/,/^begin/d' "$@" | uudecode
    * Отсортировать абзацы файла в алфавитном порядке. Абзацы разделены пустой строкой. GNU sed использует \v для вертикального выравнивания, или это может быть любой уникальный символ:
    sed '/./{H;d;};x;s/\n/={NL}=/g' file | sort | sed '1s/={NL}=//;s/={NL}=/\n/g'
    gsed '/./{H;d};x;y/\n/\v/' file | sort | sed '1s/\v//;y/\v/\n/'
    * Удалить конкретный символ (к примеру: символ возврата) из man страницы. Для использования команды 'echo' может потребоваться указать параметр -e (если вы используете Unix System V или оболочку bash):
    sed "s/.`echo \\\b`//g" (двойные кавычки необходимы в Unix окружении)
    sed 's/.^H//g' (в bash/tcsh, нажмите Ctrl-V и затем Ctrl-H)
    sed 's/.\x08//g' (hex выражение для sed 1.5, GNU sed, ssed)
    * В DOS окружении: создаем коммандный файл, который запаковывает каждый txt-файл в каталоге (в две команды):
    echo @echo off >zipup.bat
    dir /b *.txt | sed "s/^\(.*\)\.TXT/pkzip -mo \1 \1.TXT/" >>zipup.bat

Типичное использование:

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

Так:

    * cat filename | sed '10q' (используется ввод из конвеера)
    * sed '10q' filename (тот же эффект, исключая использование "cat")
    * sed '10q' filename > newfile (перенаправление вывода в файл)

Для дополнительных синтаксических инструкций, включая метод применения команд редактирования из файла, взамен командной строки, посмотрите книги Dale Dougherty и Arnold Robbins "sed & awk, 2nd Edition," (O'Reilly, 1997; http://www.ora.com), "UNIX Text Processing," by Dale Dougherty и Tim O'Reilly (Hayden Books, 1987) или учебники Mike Arst distributed in U-SEDIT2.ZIP (many sites).

Для использование всех возможностей sed-а вы должны понимать "регулярные выражения". Для этого смотрите "Mastering Regular Expressions" by Jeffrey Friedl (O'Reilly, 1997).

Могут пригодиться страницы руководства ("man") в системе Unix (Используйте "man sed", "man regexp", или раздел по регулярным выраженям в "man sed"), но страницы руководства, как правило, трудны. Они не написаны для обучения пользователей использования sed-а или регулярных выражений с нуля, а написаны как справочник для тех кто уже умеет работать с этими инструментами.
Цитирование правил (Quoting syntax):

Предшествующий пример использует одинарные кавычки ('...') вместо двойных кавычек ("...") для окружения редактируемой команды, с тех пор как sed в основном исользуется на платформах Unix. Одинарные кавычки предотращают оболочку Unix от интерпретации знака доллара ($) и обратных кавычек (`...`), которые расширяют оболочку если они заключены в двойные кавычки. Пользователи "csh" shell и происходящие от нее оболочки, также нуждаются в взятие в кавычки знака восклицания (!). С обратной косой чертой (\!) правильно запускает пример указанные выше, даже внутри одинарных кавычек.

Версии sed написанные для DOS обязательно требуют заключение редактируемых команд в двойные кавычки ("...") взамен одинарных.
Исользование '\t' в скриптах SED:

Для ясности документации, мы можем использовать выражение '\t' для обозначения символа табуляции (0x09) в скриптах.

Однако большинство версий sed-а не понимают сокращение '\t', чтобы ввести этот символ из командной строки, введите его клавишей "TAB".

'\t' поддерживается как метасимвол регулярнго выражения в awk, perl, HHsed, sedmod, и GNU sed v3.02.80.
Версии sed:

Разные версии sed-а, различаются незначителными переменами. Большинство версий не поддерживает меток (:name) или ветвление инструкций (b,t) внутри команд редактирования. Хотя поддерживают их в конце команд. Желательно использовать синтаксис исключая метки и ветвления инструкций, несмотря на популярность GNU версии sed-а, позволяющий более краткий и красивый синтаксис.

Когда читатель смотрит GNU версию sed-а, поддерживающего боле лаконичный синтаксис и видит такую длинную команду, как эту:

    * sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d

это подбивает к изученю GNU версию sed-а, для укорачивания команды:

    * sed '/AAA/b;/BBB/b;/CCC/b;d'
    * sed '/AAA\|BBB\|CCC/b;d'

В дополнение запомните: многие версии sed-а принимают команду, типа "/one/ s/RE1/RE2/", но не принимают типа "/one/! s/RE1/RE2/" - содержащую пробел перед "s".
Оптимизация по скорости:

Для необходимого ускорения выполнения программы (к примеру на больший файлах, медленном процессоре или медленном носителе), замена будет более быстрой если искомое условие будет продублированно перед инструкцией "s/.../.../". Пример:

    * sed 's/foo/bar/g' filename (стандартная команда замены)
    * sed '/foo/ s/foo/bar/g' filename (выполняется быстрее)
    * sed '/foo/ s//bar/g' filename (укороченный синтаксис предыдущей команды)

В однострочном выводе на печать или удалении строк (при неполной обработке файла), используйте команду выхода "quit" (q) в скрипте - это резко сократит время обработки больших файлов. Пример:

    * sed -n '45,50p' filename (вывести на печатать линии с 45 по 50)
    * sed -n '51q;45,50p' filename (тоже самое, но работает быстрее)

Если Вы хотите добавить свой скрипт или нашли ошибку в этом документе, пожалуйста отправьте e-mail составителю. Также укажите составителю используемую Вами версию sed-а, операционную систему составителю и обозначьте проблему. Чтобы охарактеризовать скрипт как одно-строковый, команда должна содержать не больше 65 символов.

Источник
[свернуть]

И ещё для себя насобирал из различных источников справку по sed, типа мана. Может кому будет полезна. Тоже под спойлером.

Открыть содержимое (спойлер)
sed
Имя

sed - потоковый редактор

Сценарий

sed [-Ealn]command [file ...]
sed [-Ealn] [-e command] [-f command_file] [-i extension] [file ...]


Описание

SED копирует строку из input (стандартный или указываемый набор файлов) в PATTERN SPACE (некоторая область), и к этой строке применяет все команды, адреса которых попадают в PATTERN SPACE . Затем PATTERN SPACE копируется в output . (Фактически в PATTERN SPACE находится одна строка, за исключением команды N , см. Функции SED ).

Одна команда может быть указана, как первый аргумент sed. Множественные команды могут быть указаны использованием опций -e или -f. Все команды применяются в порядке их указания, вне зависимости от их происхождения.

Доступны следующие опции:

-n, --quiet, --silent
    подавлять автоматический вывод пространства шаблонов.

-e сценарий, --expression=сценарий
    добавить сценарий к командам для исполнения

-f файл-сценария, --file=файл-сценария
    добавить содержимое файла сценария к командам для исполнения.

-i[суффикс], --in-place[=суффикс]
    редактировать файлы "на месте" (создает резервную копию, если задан суффикс)

-l N, --line-length=N
    установить желаемую длину строки при переносе строк (line-wrap) для команды `l'

-r, --regexp-extended
    использовать расширенные регулярные выражения

-s, --separate
    рассматривать входные файлы раздельно, а не как один продолжающийся поток

-u, --unbuffered
    загружать как можно меньше данных на входе и сбрасывать как можно чаще буфера на выходе

--help
    отобразить эту подсказку и выйти

-V, --version
    вывести информацию о версии и выйти

При использовании большого сценария возможен следующий способ: создается файл, в котором записываются команды sed, файл делается исполняемым, в начало файла добавляется строка:
#!/bin/sed -f

Форма команд sed следующая:

[address[,address]]function[arguments]

Пробелы (whitespaces) могут быть вставлены до первого адреса и  частями функции команды.

Обычно sed циклически копирует строку ввода, не включая завершающий символ новой строки, в шаблон пробелов, (до тех пор, пока кто-нибудь не оставит ``D'' функцию) применяет все команды с адресами которые выбрали этот шаблон, копирует шаблон на стандартный вывод, добавляя символ новой строки и удаляя шаблон.

Некоторые функции используют hold space, для сохранения всего или части шаблона для последующего поиска.


         Адреса Sed

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

Командная строка без адресов выбирает каждый шаблон

Командная строка с одним адресом выбирает все шаблоны, которые совпадают с адресом.

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

Редактирование команд может применяться к  невыбранным шаблонам, через использование символа (``!'').

Допускается задание адреса в форме 'ПЕРВАЯ~ШАГ', что соответствует каждой строке ШАГ начиная от строки ПЕРВАЯ. Например, "sed -n 1~2p" напечатает все нечётные строки, адреса 2~5 будут соответствовать каждой пятой строке начиная со второй. (Это расширение GNU.)


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

Регулярные выражения используемые в sed, по умолчанию, являются основными регулярными выражениями , но вместо них могут использоваться раширенные (новые) регулярные выражения, если будет использован флаг -E.

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

1. В контекстном адресе, любой символ отличный от обратного слеша (``\'') или символа новой строки, может использоваться для разграничения регулярного выражения. Так же, использование обратного слеша перед разграничительным символом, заставляет символ являться литерой. Например, в контекстном адресе \xabc\xdefx, разграничивающим символом в регулярном выражении является ``x'', второй ``x'' будет являться литерой, поэтому регулярное выражение будет ``abcxdef''.

2. последовательности \n совпадает с символом новой строки, встроенным в шаблон. Вы не можете использовать литеры символа новой строки в адресе, или команде подмены.

Единственной особенностью присущей регулярным выражениям sed является особенность быть по умолчанию по отношению к последему используемому регулярному выражению. Если регулярное выражение пустое, то`сть указан только разграничивающий символ, в таком случае будет использовано последнее использовавшееся регулярное выражение. Последнее регулярное выражение определяется как последнее использовавшееся регулярное выражение, как часть адреса или команды подмены, во время запуска, а не во время компиляции. Например, команда ``/abc/s//XXX/'' заменит ``XXX'' на шаблон ``abc''.

Для осуществления отбора строк для редактирования, в адресах команд SED допускается использование регулярных выражений, заключенных в "/ /" и определяемых следующим образом:

    * Регулярное выражение указывается в разделителях: "/ /" ;
    * любой символ (кроме специальных: \[.^*$ ) является регулярным выражением себя;
    * ^ в начале регулярного выражения указывает на пустой символ в начале регулярного выражения. (Т.е. на начало строки)
    * $ в конце регулярного выражения указывает на пустой символ в конце регулярного выражения. (Т.е. на конец строки);
    * \n - вставленный newline (новая строка);
    * . - любой символ (кроме обыкновенного newline );
    * * - стоящая за регулярным выражением означает любую последовательность вхождений этого выражения, начиная с 0;
    * \? - стоящий за регулярным выражением означает 0 или 1 вхождений этого выражения;
    * [ ] - указывает на один из символов, приведенных внутри;
    * [^ ] - указывает на один из символов, кроме приведенных внутри;
    * \ - перед любым символом, кроме цифр и "(" , ")" , означает этот символ. ( Экранирование специальных символов).
    * \(x\) -, где x - регулярное выражение, указывает на x .
    * \d -, где d - цифра, указывает копию d -того выражения, которое заключалось в скобки "\(" и "\)" ;
    * конкатенация регулярных выражений является регулярным выражением.

Примеры:

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

/ol.*ga/ - указывает на строки, содержащие "olga" , "olabcga" ,....;

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

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

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

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

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


Два пространства

В sed нет переменных, однако есть две области памяти, с которыми можно работать фактически как с переменными. Эти области называют pattern space (пространство образца) и hold space (скорее пространство трюма). В этой статье будем их называть просто: pattern и hold.

Pattern space

pattern содержит последнюю считанную из файла строку (справедливости ради следует сказать, что обе области могут содержать не только одну строку, а множество строк, разделенных символом newline (\n) ). Именно с ней работают основные команды. В pattern читается очередная строка. Здесь помещается результат выполнения некоторых команд

Hold space

hold - это действительно трюм, здесь могут содержаться строки на протяжении всей работы скрипта. Между hold и pattern можно производить обмен данными (добавление, замещение, обмен)


         Функции sed

В следующем списке команд, максимальное количество разрешенных адресов для каждой команды показывается как [0addr], [1addr], или [2addr], представляя ноль, один или два адреса. Аргумент text содержит одну или более строк. Что бы включить символ новой строки в текст, поставьте перед ним символ обратного слеша. Другие символы обратного слеша в тексте удаляются и следующие за ними символы рассматриваются как литеры.

Функции ``r'' и ``w'' берут опциональный параметр файла, который должен быть отделен от функционального символа пробелом (whitespace). Каждый файл, заданный как аргумент для sed'а, создается (или содержимое его урезается) прежде, чем начнется любая обработка ввода.

Функции ``b'', ``r'', ``s'', ``t'', ``w'', ``y'', ``!'', и ``:'' принимают дополнительные аргументы. Следующий пример показывает, какие аргументы должны быть отделены из символов функций, пробелами (whitespaces).

Две функции составляют список функций. Список функций sed разделяется символами  новой строки, как показано в следующим примере:

{ function
  function
  ...
  function
}

``{'' может предворяться пробелом и сопровождаться пробелом. Функции могут  предворяться пробелом. Звершающая ``}'' может пердворяться символом новой строки или пробелом.

[2addr]function-list  Запускает  список функций только, когда выбран шаблон.

[1addr]a\
   text  Добавить "text" после указанной строки (вывести), потом считать следующую. Команда не изменяет значение номера строки.

[2addr]b[label]  Перейти к команде :, содержащей label. Если метка пуста, перейти на конец сценария.

[2addr]c\
   text  Удалить pattern space и вывести "text" на output. Команда не изменяет значение номера строки.

[2addr]d  Удалить pattern space. Все команды после этой команды не исполняются. После выполнения команды считывается следующая строка файла и выполнение команд начинается сначала. Влияет на счётчик строк.

[2addr]D  Удалить pattern space до вставленной newline.

[2addr]g  Заместить содержимое pattern space содержимым буфера hold space.

[2addr]G  Добавить к содержимому pattern space символ новой строки, сопровождаемый содержимым hold space.

[2addr]h  Заместить содержимое буфера hold space на содержимое pattern space.

[2addr]H  Добавить к содержимому буфера hold space символ новой строки, сопровождаемый содержимым pattern space.

[1addr]i\
    text  Вывести текст на output перед указанной строкой. Команда не изменяет значение номера строки.

[2addr]l (буква эль). Записывает шаблон на стандартный вывод в визуально однозначной форме. Эта форма следующая:
обратный слэш               \\
сигнал                      \a
form-feed                   \f
возврат каретки             \r
табуляция                   \t
вертикальня табуляция       \v

Непечатные символы записываются как трехзначные восмеричные номера (предваряемые обратным слешем) для каждого байта в символе (наиболее важные байты сначала).
Длинные строки переносятся с указанием точки переноса в виде обратного слеша  сопровождаемого символом новой строки. Конец каждой строки указан символом ``$''.

[2addr]n  Вывести pattern space на output и считать следующую строку. Прекращает выполнение команд скрипта для текущей строки.

[2addr]N  Добавить следующую строку к pattern space , разделяя строки вставленным newline.

[2addr]p  Скопировать pattern space на output.

[2addr]P  Скопировать pattern space до первой вставленной newline на output.

[1addr]q  Переход на конец input . Вывести указанную строку, (если нет флага -n ) и завершить работу SED.

[1addr]r  Читать содержимое rfile и вывести его на output прежде чтения следующей строки. Если file не может быть прочитан,  по любой причине, он тихо игнорируется и состояние ошибки не устанавливается.

[2addr]t [label]
Проверить. Перейти к команде :, содержащей label, если со времени последнего чтения входной строки или последнего выполнения команды t в буфере выполнялись подстановки (с помощью функции "s"). Если метка пуста, перейти на конец сценария.

[2addr]w  Добавить pattern space к концу файла wfile. (Максимально можно использовать до 10 открытых файлов.) При первом выполнении w файл будет стёрт. При последующих вызовах w будет выполняться добавление. При каждом выполнении команды sed файл перезаписывается.

[2addr]x  Поменять местами содержимое pattern space и буфера hold space.

[2addr]y/str1/str2/
Заменить все вхождения символов из str1 на соответствующие из str2 . Длины строк должны быть равными.

[2addr]!function
[2addr]!function-list
Применяет функцию или список функций ({}) только для строк которые не выбраны адресом.

[0addr]:label
Устанавливает метку для перехода по "b" и "t" командам.

[1addr]=  Выводит номер строки на output как строку.

[2addr]{ - Выполняет функции до "}" , только когда выбрано pattern space . Группировка функций.

[0addr]  Пустая команда игнорируется.

[0addr]#  Комментарии.


         Функция контекстной замены

Формат:

[2addr]s/< Регулярное выражение > /< Замена > /< флаги >

Функция s заменяет вхождение < Регулярного выражения > в pattern space на < Замену > .

< Регулярное выражение > : Аналогично выше данному, но может быть заключено не в "/ /" а в любые другие символы (не " " (пробел) и не newline ).

< Замена > : Любой набор символов. Используются специальные символы:

"& " - Заменяется на строку, указанную в регулярном выражении.

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

< Флаги > :

N - Создавать замену только для N' повторений регулярного выражения в шаблоне.

g - Глобальная замена: заменить все вхождения в строке.

p - Печатать (выводить на output ) строки, в которых была осуществлена замена.

w wfile - Выводить в файл wfile строки, в которых была осуществлена замена. Если замещаемая строка совпадает с замещаемой, она все еще расценивается как замещение.

Примеры:

s/to/by/w changes - Заменить в тексте первое вхождение "to" в каждой строке, если таковое есть, на "by" и измененные строки сохранить в файле "changes" .

/iiii/s/[Oo]lga/ Olga V.Galina/p - Заменить в тексте, в строках, где встречается вхождение "iiii" , первое вхождение подстроки "olga" или "Olga" на " Olga V.Galina" , при этом измененные строки выводить на печать.

s/[.,;:?]/*sign& *sign& **/g - Заменить в тексте каждое вхождение одного из знаков ".,;:?" в строку на "*sign& *" , где & будет тем знаком, который стоял прежде, например, "." на "*sign.*" , "?" на "*sign?*" и т. д.
[свернуть]
Edimus, ut vivamus; nоn vivimus, ut edamus.

Babay

#21
Здравствуйте!
orlyanuch , у меня (надеюсь, что последние по этой книге :-[) 2 вопроса (часть 3, Гл. 13 "Регистрация в системе" (стр. 158-165) и Гл. 14 "Переменные среды и интерпретатора shell" (стр. 165 - 183):
1) Где это все (например, см. вложение) отрабатывается? Надо писать файл и запускать его, как awk и др.? (В терминале пробовал - ничего - ошибка и все тут!) 
2) Это вообще для чего надо? Пригодиться или можно "перепрыгнуть" на следующие главы "Сценарии" и т.д., и все? (Может автор таким образом объем нагонял? А так дальше по книге, вроде бы, (тьфу-тьфу-тьфу!!!) все понятно! Пробежался - там все "земное" (это вот то-то, для того-то), не так как в гл. 13 и 14 "из космоса и для космоса").

[вложение удалено администратором]
Ин дер гроссе фамилиен нихт клювен клац-клац...

ihammers

#22
Цитата: Babay от 08 марта 2012, 15:30:52
...
1) Где это все (например, см. вложение) отрабатывается? Надо писать файл и запускать его, как awk и др.? (В терминале пробовал - ничего - ошибка и все тут!) 
...
Изучать данный пункт стоит. 
В терминале, например для bash переменные будут задаваться следующим образом:

~$ export SUPER=20
~$ echo $SUPER
20
~$ export SUPER=last.txt
~$ echo $SUPER
last.txt

А для csh:
% setenv TEST y
% echo $TEST
y


PS: без export в bash должно работать.
Debian GNU/Linux Bookworm, LXQt/OpenBox: AMD Ryzen 5 5600G / 64Gb RAM
_______________________________
Debian GNU/Linux Bookworm, без графики: AMD Phenon X4 / 16Gb RAM
_______________________________
Debian GNU/Linux Bookworm, LXQt/OpenBox: Acer Aspire One 722 AMD C60 / 8Gb RAM / ATI HD6290

Babay

#23
Цитата: ihammers от 08 марта 2012, 16:08:14Изучать данный пункт стоит. 
Ок! Понял!
Цитата: ihammers от 08 марта 2012, 16:08:14В терминале, например для bash переменные будут задаваться следующим образом:
(Черт возьми, -  на этот раз никаких ошибок!)
Как я понял, у нас в Линуксе надо отбросить всякие фигурные и круглые скобки, кавычки и т.д. для выделения/отделения этих шеловских переменных - тогда код из книги работает! (Вот попробуй, догадайся об этом сам... 8)).
Цитата: ihammers от 08 марта 2012, 16:08:14PS: без export в bash должно работать.
Работает!
(Даже у меня работает!!! :D)

СПАСИБО!!!

Модератору:

А почему бы не сделать в "Программировании" раздел Shell-программирования (С, C#, Jawa и т.д.)?
Первой темой можно было бы сделать мои темы с вопросами по Shell, под названием "Книга Тейнсли Д  "Linux и UNIX. Программирование в Shell. Руководство разработчика".

P.S.

Нет, ihammers, подождите...

Насчет шеловских переменных  я понял -  изучать надо!
А вот гл. 13,"Регистрация в системе" зачем вообще нужна в шелл-программировании? ???
Ин дер гроссе фамилиен нихт клювен клац-клац...

ihammers

Открыть содержимое (спойлер)
Цитата: Babay от 08 марта 2012, 16:52:50
...
P.S.

Нет, ihammers, подождите...

Насчет шеловских переменных  я понял -  изучать надо!
А вот гл. 13,"Регистрация в системе" зачем вообще нужна в шелл-программировании? ???
Данную книгу не читал, но могу предположить, что глава, эта и следующая содержит информацию о наследовании перемененных.  Или о чём-то другом :D.
[свернуть]
Debian GNU/Linux Bookworm, LXQt/OpenBox: AMD Ryzen 5 5600G / 64Gb RAM
_______________________________
Debian GNU/Linux Bookworm, без графики: AMD Phenon X4 / 16Gb RAM
_______________________________
Debian GNU/Linux Bookworm, LXQt/OpenBox: Acer Aspire One 722 AMD C60 / 8Gb RAM / ATI HD6290

orlyanuch

#25
Там на скриншоте опечатки - круглых скобок не должно быть, только фигурные.

Цитата: Babay от 08 марта 2012, 16:52:50Как я понял, у нас в Линуксе надо отбросить всякие фигурные и круглые скобки, кавычки и т.д.

В корне неправильно  >:(
Фигурные  скобки бывают необходимы при обозначении переменных, простейший пример:
PATH=${PATH}:/home/user/bin
В данном случае в PATH добавляется каталог /home/user/bin, и без фигурных скобок не обойтись. Они как бы отделяют переменную от следующих символов, которые пишутся слитно с ней. Вроде бы работает и без этих скобок, но если ты свой скрипт запустишь на компьютере со старой версией bash, то выпадет ошибка. Поэтому следует приучить себя к использованию фигурных скобок.
Так же фигурные скобки нужны при подстановке параметров
Кавычки тоже бывают необходимы. Я вообще приучил себя абсолютно все переменные в скриптах брать в двойные кавычки после того, как несколько раз много времени потратил на поиск ошибок, возникающих из-за отсутствия всего пары кавычек.
Вот здесь про них написано подробно.
Edimus, ut vivamus; nоn vivimus, ut edamus.

Babay

#26
Цитата: orlyanuch от 08 марта 2012, 19:45:35Там на скриншоте опечатки - круглых скобок не должно быть, только фигурные.
Цитата: orlyanuch от 08 марта 2012, 19:45:35В корне неправильно  >:(

(Вот из-за таких вот мелочей-опечаток и не получается...).
Насчет скобок, кавычек - понял!  За совет-предостережение Большое Спасибо!

P.S.

orlyanuch, а можете пояснить: все-таки  для чего эта 13-я глава? Я ее никак не пойму! (Это же, насколько я понимаю, "чисто"  юзерские дела - настройки/подстройки ОС под себя... или же, у меня такое впечатление, что она вообще не отсюда - может предназначалась для другой книги?).
Как она соотноситься с программирование в шелл?
Ин дер гроссе фамилиен нихт клювен клац-клац...

orlyanuch

Ну, знания никогда не бывают лишними  :)
А если что-то непонятно, то ведь там написано
ЦитироватьЕсли вам не понятны некоторые из приведённых выше команд, не стоит огорчаться. Все команды описаны далее в этой книге. А к данному листингу можно вернуться в любой момент.
И ещё, в книге часто упоминается команда pq, к примеру
pq /etc/profile
Это какой-то старый просмотрщик, у нас его нет. Стоит писать
less /etc/profile
И у нас все пользовательские настройки находятся в файле ~/.bashrc
Edimus, ut vivamus; nоn vivimus, ut edamus.

Babay

Ок, понял!
(Но, я это сейчас все-таки пропущу! Лучше потом, по специализированной линуксовой литературе это пройду! А то и непонятно и времени нет - шелл урывками изучать получается!)

Спасибо, orlyanuch!
Ин дер гроссе фамилиен нихт клювен клац-клац...

orlyanuch

#29
После изучения этой книги (но именно после) рекомендую изучить Искусство программирования на языке сценариев командной оболочки
Там опечаток точно нет  :)
А эта книга, не смотря на все опечатки, хорошо развивает так называемую культуру программирования. Имхо
Edimus, ut vivamus; nоn vivimus, ut edamus.