$
записывает строки, соответствующие
"шабл"
, в
файл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
для изменения порядка выдачи файлов.
Хотя редактор
sed
способен на гораздо большее, чем мы вам продемонстрировали, включая проверку условий, циклы и ветвления, запоминание предыдущих строк, и, конечно, в нем допустимы многие команды редактора
ed
, описанные в приложении 1. Тем не менее в основном sed используется так, как было показано; одна или две простые команды редактирования, а не длинные и сложные последовательности. В табл. 4.2 собраны некоторые команды
sed
, хотя и не приведены операции над несколькими строками.
a\
| Добавлять строки к выходному потоку, пока одна из них не закончится на \
|
b label
| Перейти на команду: label
|
c\
| Заменить строки на последующий текст, как в команде a
|
d
| Удалить строку; прочесть следующую входную строку |
i\
| Вставить последующий текст перед следующим выходным потоком |
l
| Выдать строку, напечатав все невидимые символы |
p
| Выдать строку |
q
| Выйти |
r file
| Читать file , содержимое его переслать в выходной поток |
s/old/new/f
| Заменить old на new . Если f =g , заменить все вхождения; f =p , вывод; f =w файл, запись в файл |
t label
| Проверка: переход на метку, если была замена в текущей строке |
w file
| Записать строку в файл |
y/str1/str2/
| Заменить каждый символ строки str1 на соответствующий символ строки str2 (диапазоны недопустимы) |
=
| Выдать текущую нумерацию входной строки |
!cmd
| Выполнить команду sed cmd , только если строка не выбрана |
: label
| Установить метку для команд b и t
|
{
| Команды до соответствующей скобки } рассматривать как группу |
Таблица 4.2: Сводка команд
sed
Редактор
sed
удобен потому, что позволяет работать с произвольно длинными входными строками. Это "быстрый" редактор, который сходен с редактором
ed
в интерпретации регулярных выражений и в обработке отдельных строк. Однако, с другой стороны, его возможности запоминания ограничены (трудно запомнить текст от одной строки до другой) — делается только один проход по данным, нельзя двигаться назад, нет способов прямой адресации типа
/.../+1:
и нет средств для работы с числами, т.е. он является чисто текстовым редактором.
Упражнение 4.5
Измените команды
older
и
newer
так, чтобы они не включали файл-аргумент в свой выходной поток. Измените их так, чтобы файлы выдавались в обратном порядке.
Упражнение 4.6
С помощью редактора
sed
сделайте программу
bundle
совершенно надежной. Подсказка: в конструкции "документ здесь" слово, отмечающее конец данных, распознается только в том случае, когда оно совпадает со строкой полностью.