next up previous contents
Next: 9. Подсистема сканирования, анализа Up: 8. Потоковый редактор текста Previous: 8.2 Вызов sed

Подраздел


8.3 Команды редактирования sed

Программа редактирования, которую интерпретирует sed, состоит из одной или более команд редактирования, которые могут находиться как в командной строке, так и в файле, который указан в командной строке (параметры -e, -f, -expression, -file). В данном разделе мы будем иметь в виду одну программу или скрипт для═редактирования, который является сцеплением всех отдельных команд и скриптов редактирования упомянутых в командной строке (неважно непосредственно в строке или в файле).

Каждая команда редактирования состоит из следующих частей:

8.3.1 Адрес во вводном тексте

Адресация элементов текста может быть в одной из нижеследующих форм:

number

Определение номера вводной строки number указывает только одну строку с номером number. Заметим, что sed постоянно считает номера строк начиная с первой введ©нной строки вне зависимости от количества вводных файлов.

firstEstep

Это расширение GNU означает, что данному выражению удовлетворяют каждая step-ная строка, которая начинается с подстроки first. В частности, будут выбраны строки из вводного файла, если существует такое неотрицательное n, что номер текущей строки равен first+(n*step). Таким образом, чтобы выбрать все не©тные строки, следует использовать выражение 1~2. А если вы хотите выбрать каждую третью строку начиная со 2-ой строки, то следует использовать 2~3. Если вы захотите указать каждую пятую строку начиная с 10-ой, то - 10~5. Наконец, странное выражение 45~0 будет означать 45-ую строку.

$

Этот символ означает последнюю строку в последнем вводимом файле.

/regexp/

Этот адрес соответствует всем строкам вводного файла, содержание которых удовлетворяет регулярному выражению regexp (смотрите также 4.5). Если внутри регулярного выражения должна использоваться косая черта (/), то следует использовать комбинацию \/.

C%regexp%

Такое выражение также соответствует всем строкам вводного файла, содержание которых удовлетворяет регулярному выражению regexp. Здесь на месте знака % может быть любой символ. Такая запись оказывается удобнее, если, например, вам требуется использовать много слешей внутри regexp.

/regexp/I
C%regexp%I

Модификатор I (расширение GNU) используется, чтобы сделать поиск regexp независимым от регистра, в которых символы представлены во вводном потоке.

Если не указано никакого адреса, то все строки вводного потока подвергаются действию команд(ы) редактирования. Если имеется один адрес, то лишь те строки подвергается действию команд редактирования, которые удовлетворяют адресу.

Адресный интервал может быть обозначен как пара адресов, раздел©нных запятой. Адресный интервал включает все строки вводного файла включительно начиная со строки, соответствующей первому адресу, до строки, соответствующей второму адресу. Если второй адрес является регулярным выражением regexp, тогда проверка на соответствие начн©тся со строки следующей за первым адресом. Если второй адрес есть целое n, которое меньше или равно первому адресу, то лишь одна строка будет считаться соответствующей адресному интервалу.

Добавление символа ! (восклицательный знак) в конце адресной спецификации означает отрицание значения соответствия. Таким образом, если знак ! следует после адресного интервала, то вс© выражение будет означать все строки не попадающие в адресный интервал.

8.3.2 Буферы данных sed

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

8.3.3 Часто используемые команды

#

Комментарий; продолжается до конца строки (до символа SPMlt;NL>;). Предупреждение:
Если вам необходимо заботиться о переносе ваших скриптов на другие операционные платформы, то заметим, что в ряде реализаций sed интерпретация строк комментариев может отличаться от описанной здесь. В частности, может допускаться лишь одна строка комментариев, которая должна содержать знак # (реш©тка) только в первой слева позиции.

В первой строке скрипта sed два символа идущие подряд #n имеют специальное значение: будет включн режим no-autoprint.

s/regexp/replacement/flags

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

Значение replacement может содержать выражения вида \n, где n есть целое от 0 до 9. Такое выражение означает ту порцию соответствия, которая заключена в n-ные по порядку специальные скобки вида \( и \). Кроме этого, внутри выражения replacement может содержаться символ &, который ссылается на полную подстроку соответствующую regexp в основном буфере. Если вы хотите ввести в replacement литеральные символы SPMamp;;, \n или \, то следует использовать перед ними знак \ (обратный слеш). Пример:

$ echo "Жужжали" | sed -n 's/Жуж/Гуж<&>/p'
Гуж<Жуж>жали
Ещ© пример:
$ echo "Жужжали Бабочки" | sed -n 's/\(жж\)\(али\)/Гуж<&>\2\1/p'
ЖуГуж<жжали>алижж Бабочки

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

Символ / (наклонная черта) может использоваться внутри выражения regexp, если ему предшествует знак \. Символ конца строки SPMlt;NL>; может использоваться внутри regexp с использованием последовательности из двух символов \n (обратный слеш и n).

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

g

Произвести замену во всех местах, а не только первой встреченной подстроки в строке.

p

Если замена имела место, то вывести результат.

number

Заменить только number-ное соответствие regexp.

w file-name

Если подстановка имела место, то результат записать в файл с именем file-name.

I

Проверять соответствие regexp вне зависимости от регистра (расширение GNU).

q

Выйти из sed без обработки остальных команд редактирования или вводного потока.

d

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

p

Вывести основной буфер (на═устройство стандартного вывода). Эта команда используется обычно в сочетании с параметром -n в командной строке.

Замечание.
Некоторые реализации sed, такие как описываемая, будут печатать все строки вводного файла дважды, если режим auto-print не отключ©н и использована команда p. Другие варианты sed могут печатать каждую строку лишь однажды. Оба способа поведения sed не являются ошибкой.

n

Если режим auto-print не выключен, вывести основной буфер на устройство стандартного вывода, затем ввести в основной буфер следующую строку из вводного потока. Если вводной поток заверш©н (больше нет записей на вводе), тогда sed завершает сво© выполнение без обработки остальных команд в случае их наличия.

BcommandsD
Группа команд редактирования commands может быть заключена в фигурные скобки.

8.3.4 Прочие команды sed

Здесь обсуждаются команды sed, которые тоже очень полезны при составлении скриптов и редактировании текстов внутри скриптов.

y/source-chers/dest-chars/

Заменить во водном потоке любой символ из source-chers на соответствующий ему символ из dest-chars. Другими словами, третий символ из source-chers заменить на третий символ из dest-chars. Строки source-chers и dest-chars должны содержать одинаковое число символов. Например, команда
echo жужжал | sed y/жул/gul/
даст в результате
guggаl

aC

(Разрешается максимум один адрес.)

Строки следующие за этой командой будут помещены за обрабатываемой строкой. Все строки кроме последней должны заканчиваться знаком \ (обратный слеш). Например:

$ cat t
3 a\
Да вы переполнили \
все \
файловые системы

$ df | awk '{print $5, $6}' | sed -f t
Use% Mounted
12% /
33% /boot
Да вы переполнили 
все 
файловые системы
85% /data03
53% /data04
74% /data05
86% /usr
56% /var
99% /data02
Как видим, строки из файла t по команде a были введены после третьей строки в результирующем выводе.

iC

(Разрешается использовать один адрес.)

Немедленно вывести строки текста, следующие за этой командой. Все строки кроме последней должны заканчиваться знаком \ (обратный слеш). Например:

$ cat t
1 i\
Да вы переполнили \
всe файловые системы

$ df | awk '{print $5, $6}' | sed -f t
Да вы переполнили 
всеe файловые системы
Use% Mounted
12% /
33% /boot
85% /data03
53% /data04
74% /data05
86% /usr
56% /var
99% /data02
Как видим текст, следующий за командой i, введ©н до заданной строки. Если не задать адрес, то перед каждой строкой из вводного файла будут выводиться строки, следующие за командой i.

cC

(Разрешается использовать два адреса.)

Удалить из вводного потока строки соответствующие интервалу заданному адресами, а вместо них вывести строки, следующие после команды c. Все строки кроме последней должны заканчиваться знаком \ (обратный слеш). Например:

$ cat t
1,5 c\
Это будет новый заголовок

$df  | awk '{print $5, $6}' | sed -f t
Это будет новый заголовок
74% /data05
86% /usr
56% /var
99% /data02
Как видим, строки с 1 по 5 включительно были заменены на новую строку. Посмотрим, что будет, если не использовать адресный интервал:
$ cat t
c\
Это будет новый заголовок

$df  | awk '{print $5, $6}' | sed -f t
Это будет новый заголовок
Это будет новый заголовок
Это будет новый заголовок
Это будет новый заголовок
Это будет новый заголовок
Это будет новый заголовок
Это будет новый заголовок
Это будет новый заголовок
Это будет новый заголовок
Здесь адрес не был указан, следовательно sed заменил каждую строку из вводного потока на строку, следующую после команды c.

=

Вывести номер текущей вводной строки с последующим символом SPMlt;NL>;. Например,
$ df  | awk '{print $6}' | sed =
1
Mounted
2
/
3
/boot
4
/data03
5
/data04
6
/data05
7
/usr
8
/var
9
/data02

l

Вывести основной буфер в стандартной форме: не изображаемые символы выводятся в виде восьмеричных кодов, которым предшествует обратный слеш; длинные строки будут разбиты на более мелкие строки (места разбиения будут показаны обратными слешами); конец строки отмечается символом $ (знак доллар). Например,
$ echo "ЖужжалиБабочкиЖужжалиБабочки" | sed -n l
\366\325\326\326\301\314\311\342\301\302\317\336\313\311\366\325\326\
\326\301\314\311\342\301\302\317\336\313\311$
Как видим Кириллица распозна©тся как не изображаемые символы.

r filename

Прочесть файл с именем filename и поместить его в выводной поток в очередном цикле чтения вводного потока. Если файл с именем filename не может быть прочитан по любым причинам, то не выда©тся никакой диагностики, а файл рассматривается как файл с═нулевой длиной.

wfilename

Записать основной буфер в файл с именем filename (мне удалось проверить эту команду, когда я убрал пробел между командой и именем файла).

D

Удалить текст из основного буфера во первого конца строки. Если в основном буфере остался какой-то текст, то перейти к его обработке. В противном случае перейти к новому циклу, т.е. чтению очередной строки из вводного потока и т.д.

N

Добавить SPMlt;NL>; в основной буфер, затем поместить туда очередную строку из вводного потока. Если вводной поток исчерпан, то завершить sed без обработки оставшихся команд.

P

Вывести порцию основного буфера до первого символа SPMlt;NL>;.

h

Заместить текущее содержание дополнительного буфера содержанием основного буфера.

H

Добавить SPMlt;NL>; к содержимому дополнительного буфера. Затем добавить содержимое основного буфера к содержимому дополнительного.

g

Заместить содержимое основного буфера содержимым дополнительного буфера.

G

Добавить SPMlt;NL>; к содержимому основного буфера. Затем добавить содержимое дополнительного буфера к содержимому основного.

x

Обменять содержимое основного буфера и содержимое дополнительного буфера.

8.3.5 Команды программирования, которые понимает sed

Использование команд программирования может потребоваться в специальных случаях.

: label

(Не разрешается использовать поле адреса.)

Определить положение метки с именем label.

b [label]

Безусловный переход к метке с именем label. Если имя метки опущено, то производится переход к следующему циклу обработки вводных строк.

t [label]

Условный переход к метке с именем label. Переход выполняется в том случае успешного выполнения команды s (подстановки) с момента последнего ввода очередной строки текста или выполнялась команда условного перехода t. Если имя метки опущено, то производится переход к следующему циклу обработки вводного потока.

.

Пример простой несколько искусственной программы, которая заменяет первый встреченный в вводном потоке знак / (слеш) на букву Щ и завершает работу.

$ cat t
s/\//Щ/p
t Mylabel
b
: Mylabel
q

$ df | awk '{print $6}' | sed -n -f t
Щdev/sda6               497636     55293    416643  12% /
Здесь, в соответствии с командой s. заменяется только первый встреченный слеш. Далее производится условный переход к метке с именем Mylabel и завершается выполнение sed. До тех пор пока слеш не встретился, выполнение после команды t Mylabel продолжается и интерпретируется следующая команда b, т.е. снова вводится очередная строка вводного потока и над ней производится команда s/\//Щ/p.

<


next up previous contents
Next: 9. Подсистема сканирования, анализа Up: 8. Потоковый редактор текста Previous: 8.2 Вызов sed
Andrei Chevel
Andrei.Chevel@pnpi.spb.ru