Skip to content


Штучки с sed-ом

sed – это stream editor. Часто используется в скриптах для различных преобразований текста. Очень мощный инструмент, если понять как он работает. Ниже приведено несколько типичных примеров.

  1. Удаление из файла заданных строк.
    Пусть, например, нужно удалить строки из файла, в которых содержится подстрока "phone: xxx-xx-xx" (вместо символа x - цифры):

    sed "/phone: [0-9]\{3\}-[0-9]\{2\}-[0-9]\{2\}/ d" test.txt

    Здесь между слешами (/) задается шаблон (регулярное выражение), после него стоит оператор "d" (от слова delete), который удаляет строки файла test.txt, совпадающие с шаблоном. Результат:

    $ cat test.txt
    phone: 111-22-44
    phone: 111-22-45
    phone: 311-22-d4
    phone: 111-22-55
     
    $ sed "/phone: [0-9]\{3\}-[0-9]\{2\}-[0-9]\{2\}/ d" test.txt
    phone: 311-22-d4

    Для противоположного эффекта (если хотим удалить из файла строки, НЕ попадаюащие под шаблон) нужно добавить восклицательный знак после закрывающего регулярное выражение слеша:

    $ sed "/phone: [0-9]\{3\}-[0-9]\{2\}-[0-9]\{2\}/! d" test.txt
    phone: 111-22-44
    phone: 111-22-45
    phone: 111-22-55

    Если нужно, чтобы изменения происходили сразу в файле, без вывода в stdout, нужно добавить ключ --in-place (-i).

  2. Добавление в файл строки в определённом месте.
    Вставляем мета-тег с указанием кодировки документа перед закрывающим тегом </head> во все файлы с расширением .html в текущей директории:

    sed -i '/<\/head>/ i <meta http-equiv="Content-Type" content="text\/html; charset=utf-8">' *.html
    sed -i -r "s/\r//g" *.html

    Второй sed нужен чтобы поудалять символ возврата каретки с ASCII-кодом 13 в конце строк, который почему-то появляется в результате работы первого sed-а.

  3. Удаление из файла первых нескольких строк до тех пор, пока не встретиться пустая строка. Такое часто бывает нужно при обработке писем – если нужно отделить заголовок письма от его тела:
    $cat test.txt
    Some text in mail header.
    Another text line in mail header.
    And so on...
     
    Here starts mail body.
    Some text in mail body.
    Use sed to make things nice :)
     
    $sed '1,/^$/ d' test.txt
    Here starts mail body.
    Some text in mail body.
    Use sed to make things nice :)

    Здесь видно, что первые три строки были удалены. Шаблон /^$/ означает пустую строку (символ ^ совпадает с началом строки, а символ $ – с концом строки. Так как между ними ничего нет, то строка пустая). Выражение 1,/^$/ означает диапазон строк с 1-ой до пустой включительно. Оператор "d" – удаление.

  4. Получение заголовка usenet/email письма (удаление всего после 1-ой пустой строки):
    sed '/^$/q' /tmp/mail_message
  5. Вставить пустую строку перед строкой, совпадающей с регулярным выражением “regex”:
    sed '/regex/{x;p;x;}' test.txt
  6. Вставить пустую строку после строки, совпадающей с регулярным выражением “regex”:
    sed '/regex/G' test.txt
  7. Удаление комментариев и пустых строк. Допустим, мы хотим в каком-то конфиге посмотреть только самую его суть, не отвлекаясь на комментарии и объяснения что означают используемые опции. Для этого используем такую простую команду:
    $egrep -v "^#" /etc/snmp/snmpd.conf | sed '/^$/ d'

    В результате grep уберет из файла /etc/snmp/snmpd.conf строки, в начале которых стоит символ решётки (но оставит пустые строки), а следующий за ним sed найдёт и удалит строки, у которых между началом и концом строки ничего нет.

  8. Замена текста. Для этого используется оператор s///:
    $cat test.txt
    I want to have nice house with 4 rooms.
     
    $sed "s/\(nice\)/very \1/" test.txt | sed "s/[0-9]/12/"
    I want to have very nice house with 12 rooms.

    В операторе замены s (чаще всего используется его вариант s///) между 1-ым и 2-ым слешем указывается шаблон, который нужно найти для замены, а между 2-ым и 3-им слешем – текст, НА который нужно заменить шаблон. Если в шаблоне используются круглые скобки (их нужно экранировать обратными слешами), то текст между скобками будет доступен для использования во второй части оператора (это называется backreference). Для вставки текста, заключенного в 1-ую пару скобок, применяется конструкция \1, для текста между второй парой скобок – \2 и т.д. Символ амперсанда (&) в правой части используется для вставки текста, который совпал с регулярным выражением в левой части. Вместо слеша в операторе s можно использовать любой другой символ, например:

    $ echo "I want to have a nice house with 4 rooms." | sed "s|nice|very &|"
    I want to have a very nice house with 4 rooms.

    Если нужно заменить все вхождения шаблона в строке, а не только первое, то нужно использовать флаг g (от слова global):

    $ echo "AAABBBCCC" | sed "s/A/X/"
    XAABBBCCC
    $ echo "AAABBBCCC" | sed "s/A/X/g"
    XXXBBBCCC

    Если нужно заменить не первое вхождение шаблона в тексте, а какое-то N-ое, то нужно использовать флаг N (который также можно комбинировать с флагом g --- в этом случае заменится N-ое И все последующие совпадения шаблона в тексте):

    $ echo "AAAA-BBBB-CCCC" | sed "s/A/X/2"
    AXAA-BBBB-CCCC
    $ echo "AAAA-BBBB-CCCC" | sed "s/A/X/3"
    AAXA-BBBB-CCCC
    $ echo "AAAA-BBBB-CCCC" | sed "s/A/X/2g"
    AXXX-BBBB-CCCC
  9. Удаление HTML-тегов
    sed -e :a -e 's/<[^>]*>//g;/</N;//ba' index.html

    Фрагмент ;/</N;//ba предназначен для удаления тегов, растянутых на несколько строк. Без него будут удаляться только те теги, которые были закрыты угловой скобкой в той же стройке, в которой были открыты.

  10. Удаление символов перевода строки (объединение всех строк файла в одну)
    cat /tmp/file.txt ; echo ; sed ':a; /$/N; s/\n//; ta' /tmp/file.txt
    Это строка N1
    А это строка номер 2
    This is line number 3
     
    Это строка N1А это строка номер 2This is line number 3
  11. Преобразование регистра. Конвертация из строчных в прописные:
    $ echo "UPPer And lowER CASE mixed" | sed 's/.*/\U&/'
    UPPER AND LOWER CASE MIXED

    Конвертация из прописных в строчные:

    echo "UPPer And lowER CASE mixed" | sed 's/.*/\L&/'
    upper and lower case mixed
  12. Удаление последней (лишней) запятой из JSON-файла:
    $ cat somefile.json | sed -zr 's/,([^,]*$)/\1/'

Posted in *nix, Howto.

Tagged with .


2 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. Vityok says

    Еще один одна полезный рецепт:

    вставка текста SomeText в начало последней строки файла:

    sed -i -r "$,$ s/(.*)/SomeText \1/" file.txt

  2. Петровский says

    Вывод из файла строки с заданным номером (79 для примера):
    sed -n "79 p" /path/to/file

You must be logged in to post a comment.