Основы работы с редактором потоков Sed

Редактор потоков sed – это текстовый редактор, выполняющий операции на данных, поступающих из стандартного ввода или из файла. Sed редактирует информацию построчно и в неинтерактивной форме. Это означает, что для редактирования данных нужно вызывать команду, после чего sed выполнит указания автоматически. Такой метод работы сначала может показаться запутанным и неудобным, однако, получив базовые навыки работы с sed, вы увидите, что это очень производительный и быстрый способ преобразования текста.

Данное руководство описывает основные операции и знакомит с синтаксисом, необходимым для работы с этим редактором. На самом деле, sed почти наверняка не заменит ваш обычный текстовый редактор, но он может стать удобным дополнением к нему.

Базовое использование sed

В целом sed работает с потоками текста, которые читаются из стандартного ввода или из файла.

Это означает, что вы можете направить вывод другой команды в sed для редактирования или использовать для этого предварительно созданный файл.

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

Базовый синтаксис:

sed [options] commands [file-to-edit]

Скопируйте несколько файлов в домашний каталог для дальнейшей работы с редактором:

cd
cp /usr/share/common-licenses/BSD .
cp /usr/share/common-licenses/GPL-3 .

Поскольку по умолчанию sed отправляет результаты на экран, его можно использовать в качестве программы для считывания файлов, если не передавать ему команд редактирования. Теперь попробуйте при помощи sed просмотреть содержимое файла лицензии BSD.

sed '' BSD
Copyright (c) The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
...
...

Одинарные кавычки должны содержать команды редактирования для sed. Если они не содержат никакой команды, редактор просто выведет каждую строку файла в стандартный вывод.

Чтобы посмотреть, как sed использует  стандартный ввод, передайте вывод команды cat в sed:

cat BSD | sed ''
Copyright (c) The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
. . .
. . .

Как видите, этот редактор работает и с файлами, и с потоками с одинаковой производительностью.

Вывод строк

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

Теперь попробуйте использовать команду print; чтобы запустить эту команду, достаточно указать в одинарных кавычках букву p.

sed 'p' BSD
Copyright (c) The Regents of the University of California.
Copyright (c) The Regents of the University of California.
All rights reserved.
All rights reserved.
Redistribution and use in source and binary forms, with or without
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
modification, are permitted provided that the following conditions
are met:
are met:
. . .
. . .

Как видите, теперь sed вывел каждую строку дважды. Это произошло потому, что sed получил команду «p» и вывел каждую строку файла, но помимо этого он выводит каждую строку автоматически. Получается, что теперь на кране стандартный вывод + вывод команды р.

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

Чтобы освободить результаты от повторов, добавьте в команду опцию –n, которая подавляет автоматический вывод каждой строки:

sed -n 'p' BSD
Copyright (c) The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
. . .
. . .

Теперь редактор вернул каждую строку единожды.

Диапазоны адресов

Предыдущие примеры использования sed едва ли можно назвать редактированием. Давайте попробуем изменить вывод редактора, запросив к выводу только первую строку файла.

sed -n '1p' BSD
Copyright (c) The Regents of the University of California.

Как видите, чтобы запросить первую строку, достаточно указать её номер перед командой р. Чтобы запросить с первой по пятую строки, укажите диапазон строк:

sed -n '1,5p' BSD
Copyright (c) The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions

Только что sed получил запрос на диапазон адресов. Если в команде указан диапазон, то sed выполняет все задачи только на строках, которые входят в этот диапазон. Диапазон можно задать разными способами. Вот ещё один:

sed -n '1,+4p' BSD

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

Также sed может выводить строки согласно заданным интервалам. Для этого используется символ ~. Синтаксис интервалов:

A~Bcommand

В таком случае sed выполнит команду command на каждую строку B, начиная со строки A.

Например:

sed -n '1~2p' BSD
Copyright (c) The Regents of the University of California.
modification, are permitted provided that the following conditions
1. Redistributions of source code must retain the above copyright
2. Redistributions in binary form must reproduce the above copyright
documentation and/or other materials provided with the distribution.
may be used to endorse or promote products derived from this software
. . .
. . .

Удаление текста

Удалить ненужный текст можно при помощи команды d.

При использовании команды d добавлять опцию –n не нужно, тогда sed выведет все строки, которые не были удалены.

Попробуйте изменить предыдущую команду; используйте d вместо р и уберите опцию –n. В результате sed выведет те строки, которые не появлялись в предыдущем выводе.

sed '1~2d' BSD
All rights reserved.
Redistribution and use in source and binary forms, with or without
are met:
notice, this list of conditions and the following disclaimer.
notice, this list of conditions and the following disclaimer in the
3. Neither the name of the University nor the names of its contributors
without specific prior written permission.
. . .
. . .

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

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

sed '1~2d' BSD > everyother.txt

Откройте файл при помощи cat, и вы увидите только что полученный результат. В целях безопасности sed не редактирует исходный файл.

Это поведение можно изменить при помощи опции –i (in-place), которая выполняет замещающее редактирование текста, то есть изменяет исходный файл.

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

sed -i '1~2d' everyother.txt

Используйте команду cat и вы увидите, что файл был изменён.

Важно! Неосторожное использование опции –i может быть опасно!

К счастью, редактор sed предоставляет функции бэкапа.

Чтобы создать резервную копию файла, добавьте расширение .bak после опции –i.

sed -i.bak '1~2d' everyother.txt

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

Замена текста

Пожалуй, наиболее популярными функциями sed являются функции замены текст. При помощи регулярных выражений sed находит заданный шаблон текста, а затем заменяет его.

Примечание: Подробнее о регулярных выражениях – здесь.

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

's/old_word/new_word/'

Команда s (substitute) – это команда замены. Три слеша (/) разделяют разные поля текста. Для разделения полей можно использовать и другие символы, если это будет более удобно.

Например, чтобы изменить название сайта, лучше использовать другой разделитель полей, поскольку адреса содержат слеш. Например:

echo "http://www.example.com/index.html" | sed 's_com/index_org/home_'
http://www.example.org/home.html

Если последний разделитель отсутствует, sed вернёт ошибку:

echo "http://www.example.com/index.html" | sed 's_com/index_org/home'
sed: -e expression #1, char 22: unterminated `s' command

Создайте тестовый файл, чтобы поработать с заменой текста:

echo "this is the song that never ends
yes, it goes on and on, my friend
some people started singing it
not knowing what it was
and they'll continue singing it forever
just because..." > annoying.txt

Теперь попробуйте заменить слово on словом forward.

sed 's/on/forward/' annoying.txt
this is the sforwardg that never ends
yes, it goes forward and on, my friend
some people started singing it
not knowing what it was
and they'll cforwardtinue singing it forever
just because...

Как видите, редактор замещает шаблоны, не сами слова; к примеру, on в слове song было также заменено на forward, и получилось sforwardg.

Также следует обратить внимание на то, что во второй строке второе слово on (рядом с запятой) не было заменено на forward. Это произошло потому, что по умолчанию команда s выполняет замену только первого совпадения в строке, а после этого переходит к следующей строке.

Чтобы sed заменил все совпадения в файле, нужно использовать дополнительный флаг g, который помещается после шаблона замены.

sed 's/on/forward/g' annoying.txt
this is the sforwardg that never ends
yes, it goes forward and forward, my friend
some people started singing it
not knowing what it was
and they'll cforwardtinue singing it forever
just because...

Как видите, теперь редактор заменил все совпадения.

Чтобы заменить только каждое второе совпадение в каждой строке, вместо опции g нужно указать 2.

sed 's/on/forward/2' annoying.txt
this is the song that never ends
yes, it goes on and forward, my friend
some people started singing it
not knowing what it was
and they'll continue singing it forever
just because...

Чтобы узнать, в каких строках произошла замена текста, используйте опцию –n, чтобы подавить автоматический вывод:

sed -n 's/on/forward/2p' annoying.text
yes, it goes on and forward, my friend

Обратите внимание: в конце строки флаги можно комбинировать.

Чтобы выполнить поиск без учёта регистра, добавьте флаг i.

sed 's/SINGING/saying/i' annoying.txt
this is the song that never ends
yes, it goes on and on, my friend
some people started saying it
not knowing what it was
and they'll continue saying it forever
just because...

Ссылки на текст

Чтобы создать более сложный шаблон с регулярными выражениями, можно сослаться на шаблон в тексте замены.

Например, можно попробовать заменить текст от начала строки до at. Для этого используется такое выражение:

sed 's/^.*at/REPLACED/' annoying.txt
REPLACED never ends
yes, it goes on and on, my friend
some people started singing it
REPLACED it was
and they'll continue singing it forever
just because...

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

sed 's/^.*at/(&)/' annoying.txt
(this is the song that) never ends
yes, it goes on and on, my friend
some people started singing it
(not knowing what) it was
and they'll continue singing it forever
just because...

Скобки можно использовать для группирования. Чтобы сослаться на первую группу функций, используйте \1, на вторую – \2, и т.д.

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

sed 's/\([a-zA-Z0-9][a-zA-Z0-9]*\) \([a-zA-Z0-9][a-zA-Z0-9]*\)/\2 \1/' annoying.txt
is this the song that never ends
yes, goes it on and on, my friend
people some started singing it
knowing not what it was
they and'll continue singing it forever
because just...

Однако, как видите, результат неидеален. Например, вторая строка не была изменена, потому что содержит символ, который не учитывается шаблоном. Точно так же they’ll воспринимается редактором как два отдельных слова, а не как одно слово.

Подкорректируйте регулярное выражение, учитывая эти ошибки:

sed 's/\([^ ][^ ]*\) \([^ ][^ ]*\)/\2 \1/' annoying.txt
is this the song that never ends
it yes, goes on and on, my friend
people some started singing it
knowing not what it was
they'll and continue singing it forever
because... just

Теперь знаки пунктуации становятся частью слов.

Заключение

Данное руководство охватывает только основы работы с текстовым редактором sed.

Более продвинутые приёмы можно найти в следующей статье данной серии.

Tags:

Добавить комментарий