HANDY ONE-LINERS FOR SED (Unix stream editor)               23 марта, 2001
ШПАРГАЛКА ПО SED
собранные Эриком Пементом (Eric Pement) <pemente@northpark.edu> версия 5.1
Последняя версия доступна на:
   http://www.student.northpark.edu/pemente/sed/sed1line.txt
   http://www.cornerstonemag.com/sed/sed1line.txt

This file is also available in Portuguese at:
   http://www.lrv.ufsc.br/wmaker/sed_ptBR.html

Теперь и по-русски:
   http://rkorepanov.narod.ru/doc/sed.html


РАЗРЫВЫ ФЙЛА:

 # заменяем ПРОБЕЛ на двойной пробел
 sed G

 # ставим двойной пробел с уже имеющимися в файле пустыми строками. Выходной  файл
 # должен содержать не более одной пустой строки между строками текста
 sed '/^$/d;G'

 # Тройной пробел в файле
 sed 'G;G'

 # отменить двойные пробелы (предполагается, что пронумерованные строки всегда пустые)
 sed 'n;d'

ЧИСЛА:

 # ставим номер каждой строки файла (левое выравнивание). Использование табуляции (смотри
 # особенности применения '\t' в конце этого файла) в отличие от пробела сохранит отступ(ы).
 sed = filename | sed 'N;s/\n/\t/'

 # ставим номер каждой строки файла (число слева, выравненное по правому краю)
 sed = filename | sed 'N; s/^/     /; s/ *\(.\{6,\}\)\n/\1  /'

 # ставим номер каждой строки файла,но только если строка не пустая
 sed '/./=' filename | sed '/./N; s/\n/ /'

 # считаем количество строк (аналог "wc -l")
 sed -n '$='

ПРЕОБРАЗОВАНИЯ И ЗАМЕНА ТЕКСТА:

 # В СРЕДЕ UNIX: переводит DOS стандарт перевода строки (CR/LF) в формат Unix 
 sed 's/.$//'               # полагем , что все строки оканчиваются CR/LF
 sed 's/^M$//'              # в bash/tcsh, нажимем Ctrl-V затем Ctrl-M
 sed 's/\x0D$//'            # для 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

 # В СРЕДЕ ДОС: преобразуем символы перевода строк Unix  (LF) в DOS формат
 sed "s/$//"                          # способ 1
 sed -n p                             # способ 2

 # В СРЕДЕ ДОС: преобразуем символы перевода строки ДОС (CR/LF) формат Unix 
 # этого нельзя сделать DOS версией  sed. Используем "tr"
 tr -d \r <infile >outfile            # GNU tr версии 1.22 или выше

 # удаляем отступы (пробелы,табуляции) с начала каждой строки
 # выравниваем текст полностью по левому краю
 sed 's/^[ \t]*//'                    # смотри проблемы с '\t' в конце файла

 # удалить замыкающие пробелы, табуляции с конца каждой строки
 sed 's/[ \t]*$//'                    # смотри проблемы с '\t' в конце файла

 # удаляем  отступы, пробелы, табуляции и с конца , и с начала строки
 sed 's/^[ \t]*//;s/[ \t]*$//'

 # вставляем 5 пробелов в начале каждой строки (отступ для строки)
 sed 's/^/     /'

 # выравниваем весь текст справа по ширине колонки 79 символов
 sed -e :a -e 's/^.\{1,78\}$/ &/;ta'  #  78 плюс 1 пробел

 # центрируем весь текст посредине при ширине колонки 79 символов.В первом способе
 # пробелы в начале строки нужны, а пробелы в конце строки   дополняются до конца строки.
 # Второй способ, пробелы в начале строки отбрасываются в центр строки, и нет 
 # завершающих пробелов до конца строки.
 sed  -e :a -e 's/^.\{1,77\}$/ & /;ta'                     # Способ 1
 sed  -e :a -e 's/^.\{1,77\}$/ &/;ta' -e 's/\( *\)\1/\1/'  # Способ 2

 # подстановка (найти и заменить) "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 -  пустые строки удаляются
 sed '1!G;h;$!d'               # способ 1
 sed -n '1!G;h;$p'             # способ 2

 # обратный порядок символов в строке (походит на "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'

 # добавляем запятые к числовым строкам, меняя "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 ':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")
 sed '$!d'                    # способ 1
 sed -n '$p'                  # способ 2

 # печать только строк ,которые совпадают с regexp ( "grep")
 sed -n '/regexp/p'           # способ 1
 sed '/regexp/!d'             # способ 2

 # печать только строк , НЕ совпадающих с regexp (как "grep -v")
 sed -n '/regexp/!p'          # способ 1, соответствует вышеприведенному
 sed '/regexp/d'              # спопоб 2, простейший синтаксис

 # печать строки непосредственно перед regexp, но не  строки
 # содержащей regexp
 sed -n '/regexp/{g;1!p;};h'

 # печать строки непосредственно после regexp, но не строки
 # содержащей  regexp
 sed -n '/regexp/{n;p;}'

 # печать 1 строки контекста перед и после regexp,с номером строки,
 # показывающей , сколько regexp встретилось (как в "grep -A1 -B1")
 sed -n -e '/regexp/{=;x;1!p;g;$!N;p;D;}' -e h

 # grep для AAA и BBB и CCC (в любом порядке)
 sed '/AAA/!d; /BBB/!d; /CCC/!d'

 # grep для AAA и BBB и CCC (в таком же порядке)
 sed '/AAA.*BBB.*CCC/!d'

 # grep для 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;' в следующих 3 скриптах
 sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;'

 # печать параграфа если тот содержит AAA и BBB и CCC (в любом порядке)
 sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;/BBB/!d;/CCC/!d'

 # печать параграфа если тот  содержит AAA или BBB или CCC
 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 )
 sed -n '8,12p'               # способ 1
 sed '8,12!d'                 # способ 2

 # печать строки 52
 sed -n '52p'                 # способ 1
 sed '52!d'                   # способ 2
 sed '52q;d'                  # способ 3, эффективно для больших файлов

 # начиная со строки 3, печать каждой 7-ой строки
 gsed -n '3~7p'               # для GNU sed
 sed -n '3,${p;n;n;n;n;n;n;}' # для других

 # печать части файла между двумя регулярными выражениями 
 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'

 # удаление первых 10 строк файла
 sed '1,10d'

 # удалить последнюю строку файла
 sed '$d'

 # удалить последние 2 строки файла
 sed 'N;$!P;$!D;$d'

 # удалить последние 10 строк файла
 sed -e :a -e '$d;N;2,10ba' -e 'P;D'   # способ 1
 sed -n -e :a -e '1,10!{P;N;D;};N;ba'  # способ 2

 # удалить каждую 8 строку
 gsed '0~8d'                           # только GNU sed
 sed 'n;n;n;n;n;n;n;d;'                # другие sedы

 # удалить все пустые строки файла (также как и "grep '.' ")
 sed '/^$/d'                           # способ 1
 sed '/./!d'                           # способ 2

 # удалить все ПОСЛЕДОВАТЕЛЬНЫЕ строки файла , кроме первых; также
 # удаляет все пустые строки с начала и до конца файла (походит на "cat -s")
 sed '/./,/^$/!d'          # способ 1, разрешает 0 пустых в начале, 1 от EOF
 sed '/^$/N;/\n$/D'        # способ 2, разрешает 1 пустых в начале, 0 от EOF

 # удалить все ПОСЛЕДОВАТЕЛЬНЫЕ пустые строки из файла кроме первых двух:
 sed '/^$/N;/\n$/N;//D'

 # удалить  все пустые строки с начала файла:
 sed '/./,$!d'

 # удалить все завершающие файл пустые строки
 sed -e :a -e '/^\n*$/{$d;N;ba' -e '}'  # рaботает на всех sed
 sed -e :a -e '/^\n*$/N;/\n$/ba'        # также, кроме gsed 3.02*

 # удалить последнюю строку каждого параграфа
 sed -n '/^$/{p;h;};/./{x;/./p;}'

СПЕЦИАЛЬНЫЕ ПРИМЕНЕНИЯ:

 # удалим спецсимволы (overstrikes) (символ, бэкспейс) из man pages. Команда 'echo'
 # может понадобится для ключа  -e если у вас ось Unix System V или bash shell.
 sed "s/.`echo \\\b`//g"    # двойные кавычки для среды  Unix 
 sed 's/.^H//g'             # в bash/tcsh, жмите Ctrl-V затем Ctrl-H
 sed 's/.\x08//g'           # hex (16-ричное) выражение для sed v1.5

 # получаем заголовок сообщения формата Usenet/e-mail
 sed '/^$/q'                # удаляем все после первой пустой строки

 # получить тело сообщения формата Usenet/e-mail
 sed '1,/^$/d'              # удаляем все до первой пустой строки

 # получить заголовок темы письма , но без  слова "Subject: " 
 sed '/^Subject: */!d; s///;q'

 # получить начальный заголовок письма отправителя
 sed '/^Reply-To:/q; /^From:/h; /./d;g;q'

 # разобрать свойства адреса, выкинуть нафиг e-mail адрес 
 # с  1-строчного адресного заголовка (смотрите выше)
 sed 's/ *(.*)//; s/>.*//; s/.*[:<] *//'

 # добавить начальный уголок и пробел в каждую строку (квотинг сообщения)
 sed 's/^/> /'

 # удалить начальный уголок и пробел из каждой строки (антиквотинг сообщения)
 sed 's/^> //'

 # удалить теги HTML (включая многострочные теги)
 sed -e :a -e 's/<[^>]*>//g;/</N;//ba'

 # распаковать многотомные заююкоженые бинарники,удалить дополнительный заголовок
 # и инфу, которые остаются от ююкоженой части. Файлы переданные в
 # sed долны идти в правильном порядке. Версия 1 может вводиться в командной строке
 # ; версия 2 может запихиваются в запускаемые скрипты Unix shell
 # (Изменение от скрипта Рауля Деси (Rahul Dhesi)
 sed '/^end/,/^begin/d' file1 file2 ... fileX | uudecode   # Версия 1
 sed '/^end/,/^begin/d' "$@" | uudecode                    # Версия 2

 # заZIPовать каждый .TXT файл отдельно,удаляя исходный и 
 # называя каждый  .ZIP файл именем запакованного  .TXT файла
 # (под DOS: команда "dir /b" возвращает чисто имена файлов списком).
 echo @echo off >zipup.bat
 dir /b *.txt | sed "s/^\(.*\)\.TXT/pkzip -mo \1 \1.TXT/" >>zipup.bat

ТИПОВОЕ ПОЛЬЗОВАНИЕ: Sed получает одну или больше команд по порядку
и применяет их при каждой операции ввода. После этого все команды применяются
к первой строке ввода,затем первая строка выводится и вторая строка ожидает 
ввода для  обработки , а затем цикл повторяется. Предыдущие примеры предполагают
что ввод производится со стандартного <STDIN> ,например с консоли 
обычно это будет ввод трубы, вернее, канала (или контейнера)  ;) (piped input). Один из 
больших имен файлов добавляется в командную строку если нет ввода со
стандартного устройства ввода <STDIN>, посылаемого на устройство вывода (Экран).
Вот примерчики:

 cat filename | sed '10q'        # Используются каналы-контейнера
 sed '10q' filename              # такой же эффект но без кота ;) ("cat")
 sed '10q' filename > newfile    # перенаправим вывод на диск

Для дополнительных примеров , включая применение команд для ввода
команд с файла на диске , а не только в командной строке, прочитайте "sed &
awk, 2я редакция," от Даля Дугерти( Dale Dougherty) и Арнольда Руббенса
( Arnold Robbins) (O'Reilly,1997; http://www.ora.com), "Обработка текста в UNIX ," 
Даля Дугерти( Dale Dougherty) и Тима Орэйли (Tim O'Reilly) (Hayden Books, 1987) 
или учебники от Майка Арста (Mike Arst) в файле U-SEDIT2.ZIP (нуно поискать). 
Чтоб впитать силу  sed, нужно понять что такое "Регулярные выражения." Для этого,
прочитайте "Регулярные выражения" от  Джефри Фриддла (Jeffrey Friedl)
(O'Reilly, 1997).Читайте ("man") маны , может помочь в Unix ("man
sed", "man regexp", или подсекцию , посвященную регулярным выражениям в "man
ed"), но маны достаточно сложны. Они написаны не для обучения
sed или использованию regexp для чайников, но как как справочник
для использующих программы на практике.

ИСПОЛЬЗОВАНЕ КАВЫЧЕК: Представленные примеры используют одинарные кавычки ('...')
в отличие от двойных ("...") для ограничения редактируемых команд еще
во времена использования ed на Unix. Одинарные кавычки предохраняют
оболочку Unix от интерпретации знака бакса ($) и обратнокавычек
(`...`),которые использует шелл , если они окружены двойными кавычками.
Пользователям  "csh" и аналогам также нужно экранировать 
знак восклицания (!) бэкслэшем (например, \!) для правильной работы
вышепредставленных примеров,даже внутри одинарных кавычек.
Версии  sed для DOS всегда требуют двойные кавычки ("...") а не одинарные 
для ограничения редактируемых комманд.

ИСПОЛЬЗОВАНИЕ '\t' В СКРИПТАХ SED: Для чистоты документации мы использовали
выражение '\t' для вывода символа  табуляции (0x09) в скриптах.
Однако, меногие версии sed не распознают  '\t' , и для этого,когда вы пишете
эти скрипты в командной строке ,жмите вместо этого кнопочку
TAB. '\t' поддеривается регулярными выражениями в awk, perl, и HHsed, sedmod,
и GNU sed v3.02.80.

ВЕРСИИ SED: Версии sed различны, поэтому возможны некотрые различия синтаксиса.
В особых случаях, может не быть поддержки меток (:name) или ветвящихся конструкций
(b,t) в пределах редактируемых команд, кроме окончания этих команд. 
Мы использовали синтаксис который будет использоваться для большинства 
версий sed , тогда как популярные версии сед под лицензией
GNU разрешают более последовательный синтаксис. Когда читатель видит
длиннющую команду как эта:

   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      # укороченый синтаксис sed 

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

   sed -n '45,50p' filename           # печать строки  45-50 позиции файла
   sed -n '51q;45,50p' filename       # по-другому, но работает шустрее

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

 Al Aab <af137@freenet.toronto.on.ca>   # модератор "sedеров"
 Edgar Allen <era@sky.net>              # разное
 Yiorgos Adamopoulos <adamo@softlab.ece.ntua.gr>
 Dale Dougherty <dale@songline.com>     # автор "sed & awk"
 Carlos Duarte <cdua@algos.inesc.pt>    # автор "do it with sed"
 Eric Pement <pemente@northpark.edu>    # автор этого перевода
 Ken Pizzini <ken@halcyon.com>          # автор GNU sed v3.02
 S.G. Ravenhall <stew.ravenhall@totalise.co.uk> # скрипт для de-html
 Greg Ubben <gsu@romulus.ncsc.mil>      # приложения и помощь

------------------------------------------- Korepanov Roman <rk1@chat.ru> # перевод на русский язык