Литмир - Электронная Библиотека
Содержание  
A
A

Заметьте, кстати, что введение символа

|
в конце строки — это законный способ ее продолжения.

Упражнение 4.3

Используя средства этого раздела и файл

/usr/dict/words
, составьте простой анализатор правильности написания текста на английском языке. Каковы его недостатки и как их исправить?

Упражнение 4.4

Напишите программу подсчета слов на предпочитаемом вами языке программирования. Сравните ее размер, скорость и самодокументированность с соответствующим конвейером. Насколько легко вы можете преобразовать эту программу в программу проверки правильности написания текста?

4.3 Потоковый редактор

sed

Вернемся теперь к редактору

sed
. Поскольку он происходит непосредственно от
ed
, вы легко изучите его и закрепите свои знания о редакторе
ed
. Основа редактора
sed
проста:

$ sed 'список команда ed' имена_файлов...

Читаются строки по одной из входных файлов; команды из списка применяются к каждой строке по одной в указанном порядке и результат редактирования записывается в стандартный выходной поток. Например, можно заменить в любом из указанных файлов

UNIX
на
UNIX (TM)
с помощью команды:

$ sed 's/\UNIX/\UNIX\ (TM)/g' имена_файлов...> выходной поток

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

$ sed '...' файл > файл

не лучшее решение: для замены содержимого файлов нужно задействовать временный файл или другую программу. В дальнейшем мы рассмотрим программу, реализующую задачу записи в существующий файл; обратитесь к команде

overwrite
в (гл. 5).

Редактор

sed
выдает все строки автоматически, поэтому команда
p
не нужна после ввода команды замены, приведенной выше; более того, если она задается, то каждая изменяемая строка печатается дважды. Однако кавычки необходимы почти всегда, поскольку многие метасимволы программы
sed
имеют специальные значения и для интерпретатора. Рассмотрим, например, команду
du -а
, порождающую список имен файлов. Обычно она выдает размер и имя файла:

$ du -a ch4*

18 ch4.1

13 ch4.2

14 ch4.3

17 ch4.4

 2 ch4.9

$

Можно использовать

sed
, чтобы отбросить размеры файлов, но в команде редактирования нужны кавычки для защиты символов
*
и табуляции от обработки интерпретатором:

$ du -a ch4.* | sed 's/.*→//'

ch4.1

ch4.2

ch4.3

ch4.4

ch4.9

$

В команде замены удаляются все символы (

.*
) до крайнего правого символа табуляции включительно (он показан в шаблоне как
). Аналогичным способом можно выделить из вывода команды who имена пользователей и время входа в систему:

$ who

lr  tty1 Sep 29 07:14

ron tty3 Sep 29 10:31

you tty4 Sep 29 08:36

td  tty5 Sep 29 08:47

$ who | sed 's/ .* / /'

lr  07:14

ron 10:31

you 08:36

td  08:47

$

Команда

s
заменяет пробел и все, что следует за ним (максимально возможно, включая дополнительные пробелы) до следующего пробела на единственный пробел. Кавычки нужны.

Почти такую же команду

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

$ cat getname

who am i | sed 's/ .*//'

$ getname

you $

Другая команда

sed
применяется настолько часто, что мы поместили ее в командный файл с именем
ind
. Эта команда вставляет пробелы до шага табуляции; она удобна для лучшего расположения текста при печати.

Реализовать команду

ind
просто: достаточно установить символ табуляции в начале каждой строки:

$ sed 's/^/→/' $*
Первая версия ind

В этой версии символ табуляции вставляется даже в пустую строку, что не требуется. В лучшей версии используется возможность

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

sed '/./s/^/→/' $*
Вторая версия

Шаблон

/./
задает любую строку, в которой есть по крайней мере один символ, кроме символа перевода строки, поэтому команда
s
не выполняется для пустых строк. Вспомним, что
sed
выдает все строки, независимо от того, менялись они или нет, так что пустые строки по-прежнему выдаются.

Есть еще один способ определения команды

ind
. Можно выполнять команды только для тех строк, которые не соответствуют выбираемому шаблону, предварив команду знаком восклицания
'!'
. В команде

sed '/^$/!s/^/→/' $*
Третья версия

шаблон

/^$/
задает пустые строки (перевод строки сразу следует за ее началом), поэтому
/^$/!
предписывает не выполнять команду для пустых строк.

Как уже отмечалось,

sed
печатает каждую строку автоматически, независимо от того, какие операции над ней выполнялись (если только она не была удалена). Кроме того, можно использовать большинство команд редактора
ed
. Поэтому легко составить программу
sed
, которая напечатает, скажем, три первых строки входного потока, а затем завершится:

47
{"b":"248117","o":1}