Хотя автоматический вывод обычно удобен, иногда он мешает. Его можно отключить с помощью флага -n; в этом случае в выходном потоке появятся только строки, задаваемые явной командой вывода p. Например,
$ sed -n '/шаблон/p'
эквивалентен команде grep. Условие сопоставления можно инвертировать, если завершить его символом !, поэтому
$ 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 '1,10d' Удаление строк с 1-й до 10-й (=tail +11)
$ sed '1,/^$/cd' Удаление всех строк до первой пустой включительно
$ sed -n '/^$/,/^end/p' Печать всех групп строк, начиная от пустой строки до
строки, начинающейся с end
$ sed '$d' Удаление последней строки
Строки нумеруются с начала входного потока; обнуление не происходит с началом нового файла.
У команды sed есть существенное ограничение, которое, однако, отсутствует в редакторе ed: в ней поддерживается относительная нумерация строк. В частности, операции + и - не действуют в выражениях, задающих номера строк, поэтому невозможно двигаться назад во входном потоке:
$ sed '$-1d' Недопустима обратная адресация
Unrecognized command: $-1d
$
Если строка считана, предыдущая исчезла навсегда: нет способа специфицировать предыдущую строку, а именно это требуется в команде. В принципе такой способ есть в команде sed, но он слишком изощренный. (См. команду hold в справочном руководстве по UNIX.) Невозможна и относительная прямая адресация:
$ sed '/что-то/+1d' Недопустима прямая адресация
Редактор sed имеет возможность записывать в несколько выходных файлов. Например, команда
$ sed -n '/шабл/w файл1
> /шабл/!w файл2' имена_файлов...
$
записывает строки, соответствующие "шабл", в файл1, а не соответствующие — в файл2, или, если вернуться к нашему первому примеру:
$ sed 's/\UNIX(TM)/gw u.out' имена_файлов...> выход
то здесь, как и ранее, весь выходной поток записывается в файл "выход", но к тому же измененные строки записываются в файл u.out.
Иногда нужна помощь со стороны интерпретатора, чтобы в команду редактора включить аргументы командного файла. Одним из примеров служит программа newer, которая выдает все более новые, чем заданный, файлы каталога:
$ cat newer
# newer f: список файлов, созданных после f
ls -t | sed '/'$1'$/q'
$
Кавычки защищают различные специальные символы, предназначенные для редактора, оставляя $1 открытым для интерпретатора, чтобы он заменил его на имя файла. Существует альтернативный способ записи аргумента:
"/^$1\$/q"
так как $1 заменяется на аргумент, тогда как \$ становится просто $.
Аналогично можно составить программу older, которая выдает в качестве параметра все файлы, более старые, чем заданный:
$ cat older
# older f: список файлов, созданных ранее f
ls -tr | sed '/'$1'$/q'
$
Единственное различие состоит в применении флага -r в команде ls для изменения порядка выдачи файлов.