GNU sed
GNU sed
GNU sed, stream editor — потоковый редактор. Уникальная утилита с двумя буферами: основным (pattern space) и вспомогательным (hold space); а также множеством однобуквенных команд для манипуляции этими буферами.
Здесь приведён краткий обзор этой исключительно прекрасной в своей сути утилиты. Десятикратно более подробный и точно более полный и честный, но требующий времени на чтение мануал: GNU sed Manual
Основы sed
- Потоковая обработка: sed читает входные данные построчно, обрабатывает их согласно заданным командам и выводит результат. Как можно догадаться в качестве потока можно использовать и стандартный поток ввода и обычный файл, что весьма удобно.
- Работа с буферами: для работы sed использует два основных буфера — буфер шаблонов (pattern space) и холд-буфер (hold space), между которыми можно обмениваться данными.
- Однобуквенные команды: ещё в sed есть несколько десятков однобуквенных команд, которые можно комбинировать в скрипты и с помощью которых можно творить чудеса.
Как устроены скрипты для sed
Программа sed
состоит из одной или нескольких команд sed
, передаваемых с помощью опций -e
, -f
, --expression
и --file
или первого неопционального аргумента, если эти опции не используются.
Под программой sed
будем подразумевать конкатенацию всех скриптов и файлов-скриптов в порядке передачи.
Команды sed
следуют этому синтаксису:
[addr]X[options]
Где X - это однобуквенная команда sed
. [addr]
- необязательный адрес строки. Если [addr]
указан, команда X будет выполнена только для соответствующих строк. [addr]
может быть одним номером строки, регулярным выражением или диапазоном строк. Дополнительные [options]
используются для некоторых команд sed
.
Как устроены скрипты для sed
Например, следующая команда удаляет строки с 30 по 35:
sed '30,35d' input.txt > output.txt
Следующий пример печатает весь ввод до строки, начинающейся со слова «foo». Если такая строка найдена, sed
завершится с кодом 42. Если строка не найдена (и не произошло других ошибок), sed
завершится с кодом 0:
sed '/^foo/q42' input.txt > output.txt
Как устроены скрипты для sed
Команды в скрипте или файле скрипта могут разделяться точкой с запятой (;) или символами новой строки (ASCII 10).
Несколько скриптов можно указать с помощью опций -e или -f.
Следующие примеры эквивалентны - они выполняют две операции sed
: удаление любых строк, соответствующих регулярному выражению /^foo/
, и замену всех вхождений строки «hello» на «world»:
sed '/^foo/d ; s/hello/world/' input.txt > output.txt
sed -e '/^foo/d' -e 's/hello/world/' input.txt > output.txt
echo '/^foo/d' > script.sed
echo 's/hello/world/' >> script.sed
sed -f script.sed input.txt > output.txt
echo 's/hello/world/' > script2.sed
sed -e '/^foo/d' -f script2.sed input.txt > output.txt
Как передавать команды в sed
Список команд
sed -e '1d' -e '$d' file.txt # Удалить первую и последнюю строки
Чтение команд из файла
sed -f script.sed
Исполнение скрипта
sed позволяет писать и выполнять более сложные скрипты для обработки текста.
Да, как и на любом другом языке просто указываем shebang:
#!/bin/sed -f
s/foo/bar/
Адресация
Вы можете указывать, к каким строкам применять команды, используя номера строк, регулярные выражения или их комбинации.
n
: Применить команду к n-й строке.$
: Применить команду к последней строке./pattern/
: Применить команду к строкам, соответствующим шаблону.n,m
: Применить команду к диапазону строк от n до m./start/,/end/
: Применить команду к диапазону между двумя шаблонами.- Перекрестная адресация:
sed '3,/pattern/s/old/new/' file.txt # Заменяет 'old' на 'new' начиная с 3-й строки до строки с 'pattern'
- Использование метасимволов:
sed '0~2d' file.txt # Удаляет каждую вторую строку, начиная с первой
Буферы
h
: Копировать шаблон в холд-буфер.H
: Добавить шаблон к холд-буферу.g
: Копировать холд-буфер в шаблон.G
: Добавить холд-буфер к шаблону.x
: Обменять шаблон и холд-буфер.
Ввод-Вывод
p
: Печатать шаблон.n
: Прочитать следующую строку и печатать.d
: Удалить шаблон и начать следующий цикл.q
: Выйти из sed.r file
: Читать содержимое файла.w file
: Записать шаблон в файл.a\text
: Добавить текст после строки.i\text
: Вставить текст перед строкой.c\text
: Заменить строку текстом.
Редактирование
s/pattern/replacement/
: Заменить шаблон.y/source/dest/
: Транслитерировать символы.=
: Печатать номер строки.
Расширенные Команды
!
: Применить команду к строкам, не соответствующим шаблону.{}
: Группировать команды.:
: Установить метку для перехода.b label
: Перейти к метке.t label
: Перейти к метке, если была выполнена замена.N
: Добавить следующую строку к шаблону.P
: Печатать первую часть шаблона до символа новой строки.D
: Удалить первую часть шаблона до символа новой строки.
Простые примеры
- Примеры адресации:
sed -n '1,5p' file.txt # Вывести строки с 1 по 5
- Добавление, удаление и замена текста:
sed 's/old/new/g' file.txt # Заменить 'old' на 'new' во всем файле
- Многострочное удаление:
sed '/^$/,/^$/d' file.txt # Удалить пустые строки
Сложный пример 1: Переворачивание Текста
sed -re '1!G;h;$!d' forward.txt > backward.txt
Описание:
1!G
: Для каждой строки, кроме первой, добавляет содержимое холд-буфера в конец шаблона.h
: Копирует шаблон в холд-буфер.$!d
: Удаляет шаблон для всех строк, кроме последней.
Результат: Строки файла forward.txt
записываются в обратном порядке в backward.txt
.
Сложный пример 2: Инкремент Чисел
#!/usr/bin/sed -f
:d; s/9\(_*\)$/_\1/; td
s/^\(_*\)$/1\1/; tn
s/8\(_*\)$/9\1/; tn
s/6\(_*\)$/7\1/; tn # что тут происходит???
s/5\(_*\)$/6\1/; tn #
s/4\(_*\)$/5\1/; tn
s/3\(_*\)$/4\1/; tn
s/2\(_*\)$/3\1/; tn
s/0\(_*\)$/1\1/; tn
:n
y/_/0/
Описание:
:d; s/9\(_*\)$/_\1/; td
: Заменяет все 9 на _ справа налево.s/^\(_*\)$/1\1/; tn
: Добавляет 1 в начало, если строка состоит только из _.s/[0-8]\(_*\)$/nextDigit\1/; tn
: Заменяет каждую цифру на следующую.y/_/0/
: Заменяет все _ на 0.
Результат: Инкрементирует числа в файле.
Сложный пример 3: Удаление Повторяющихся Строк
sed '$!N; /^\(.*\)\n\1$/!P; D'
Описание:
$!N
: Добавляет следующую строку к шаблону, если это не последняя строка./^\(.*\)\n\1$/!P
: Печатает шаблон, если две строки в нем не одинаковы.D
: Удаляет первую часть шаблона до новой строки.
Результат: Удаляет соседние дубликаты строк.
Сложный пример 4: Преобразование Markdown заголовков в HTML
sed -e 's/^# \(.*\)$/\<h1\>\1\<\/h1\>/' -e 's/^## \(.*\)$/\<h2\>\1\<\/h2\>/'
Описание:
s/^# \(.*\)$/\<h1\>\1\<\/h1\>/
: Заменяет строки, начинающиеся с#
, на теги<h1>
.s/^## \(.*\)$/\<h2\>\1\<\/h2\>/
: Заменяет строки, начинающиеся с##
, на теги<h2>
.
Результат: Преобразует Markdown заголовки в HTML.
Регулярные выражения в sed
- Базовые и расширенные регулярные выражения: sed поддерживает оба типа регулярных выражений, что позволяет выполнять сложные поисковые запросы.
- Примеры шаблонов поиска:
sed -n '/^root/p' /etc/passwd # Найти строки, начинающиеся с 'root'
Повторение функциональности некоторых утилит с помощью sed
Здесь
- tac: переворачивает строки файлов
- cat -n: нумерует строки
- cat -b: нумерует непустые строки
- wc -c: считает количество символов
- wc -w: счиатет количество слов
- wc -l: считает количество строк
- head: печатает первые
n
строк - tail: печатает последние
n
строк - uniq: удаляет повторяющиеся соседние строки
- uniq -d: печатает повторяющиеся строки
- uniq -u: удаляет повторяющиеся соседние строки, но выводит только уникальные, т.е. те, которые в изначальном вводе были в единственном числе
- cat -s: сжатие пустых строк