Основы использования редактора Sed Stream для управления текстом в Linux
Введение
Команда sed
, сокращенно от потокового редактора, выполняет операции редактирования текста, поступающего из стандартного ввода или файла. sed
редактирует построчно и неинтерактивным способом.
Это означает, что вы принимаете все решения по редактированию при вызове команды, а sed
автоматически выполняет указания. Это может показаться запутанным или неинтуитивным, но это очень мощный и быстрый способ преобразования текста, особенно в рамках сценария или автоматизированного рабочего процесса.
В этом руководстве будут рассмотрены некоторые основные операции и представлен синтаксис, необходимый для работы с этим редактором. Вы почти наверняка никогда не замените свой обычный текстовый редактор на sed
, но он, вероятно, станет долгожданным дополнением к вашему набору инструментов для редактирования текста.
Примечание. В этом руководстве используется версия GNU sed
, используемая в Ubuntu и других операционных системах Linux. Если вы используете macOS, у вас будет версия BSD с другими параметрами и аргументами. Вы можете установить GNU-версию sed
с помощью Homebrew, используя brew install gnu-sed
.
Основное использование
sed
работает с потоком текста, который считывается либо из текстового файла, либо из стандартного ввода (STDIN). Это означает, что вы можете отправить вывод другой команды непосредственно в sed для редактирования или вы можете работать с уже созданным файлом.
Вы также должны знать, что sed
по умолчанию выводит все на стандартный вывод (STDOUT). Это означает, что без перенаправления sed
будет выводить вывод на экран, а не сохранять его в файл.
Основное использование:
- sed [options] commands [file-to-edit]
В этом руководстве вы будете использовать копию лицензии на программное обеспечение BSD для экспериментов с sed
. В Ubuntu выполните следующие команды, чтобы скопировать файл лицензии BSD в свой домашний каталог, чтобы вы могли с ним работать:
- cd
- cp /usr/share/common-licenses/BSD .
Если у вас нет локальной копии лицензии BSD, создайте ее самостоятельно с помощью этой команды:
- cat << 'EOF' > 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.
- 3. Neither the name of the University nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- SUCH DAMAGE.
- EOF
Давайте воспользуемся sed
для просмотра содержимого файла лицензии BSD. sed
по умолчанию отправляет свои результаты на экран, что означает, что вы можете использовать его в качестве средства чтения файлов, не передавая ему никаких команд редактирования. Попробуйте выполнить следующую команду:
- sed '' BSD
Вы увидите лицензию BSD, отображаемую на экране:
OutputCopyright (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
выводил каждую полученную строку на стандартный вывод.
sed
может использовать стандартный ввод, а не файл. Передайте вывод команды cat
в sed
, чтобы получить тот же результат:
- cat BSD | sed ''
Вы увидите вывод файла:
OutputCopyright (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
без каких-либо операций, будут выводить результаты непосредственно на стандартный вывод.
Давайте рассмотрим явную команду print
в sed
, которую вы указываете с помощью символа p
в одинарных кавычках.
Выполните следующую команду:
- sed 'p' BSD
Вы увидите, что каждая строка файла BSD
напечатана дважды:
OutputCopyright (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
автоматически печатает каждую строку по умолчанию, а затем вы указали ему печатать строки явно с помощью команды \p, поэтому вы печатаете каждую строку дважды.
Если вы внимательно изучите выходные данные, вы увидите, что первая строка содержит дважды, за ней дважды следует вторая строка и т. д., что говорит о том, что sed
работает с данными построчно. Он читает строку, работает с ней и выводит результирующий текст перед повторением процесса на следующей строке.
Вы можете очистить результаты, передав параметр -n
в sed
, который подавляет автоматическую печать:
- sed -n 'p' BSD
OutputCopyright (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
напечатает первую строку файла. Выполните следующую команду:
- sed -n '1p' BSD
Первая строка выводит на экран:
OutputCopyright (c) The Regents of the University of California.
Поместив число 1
перед командой печати, вы указали sed
номер строки, с которой нужно работать. С таким же успехом можно вывести пять строк (не забудьте \-n):
- sed -n '1,5p' BSD
Вы увидите этот вывод:
OutputCopyright (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 напечатать строки с 1 по 5. Вы могли бы указать это по-другому, указав первый адрес, а затем используя смещение, чтобы сообщить sed, сколько дополнительных строк нужно пройти, например:
- sed -n '1,+4p' BSD
Это приведет к тому же результату, потому что вы сказали sed
начинать с строки 1, а затем работать со следующими 4 строками.
Если вы хотите печатать каждую вторую строку, укажите интервал после символа ~
. Следующая команда печатает каждую вторую строку в файле BSD
, начиная со строки 1:
- sed -n '1~2p' BSD
Вот результат, который вы увидите:
OutputCopyright (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
. . .
. . .
Вы также можете использовать sed
для удаления текста из вывода.
Удаление текста
Вы можете выполнить удаление текста там, где ранее указывали печать текста, заменив команду p
на команду d
.
В этом случае вам больше не нужна команда -n
, потому что sed
напечатает все, что не удалено. Это поможет вам увидеть, что происходит.
Измените последнюю команду из предыдущего раздела, чтобы сделать ее
- sed '1~2d' BSD
В результате вы видите каждую строку, которую вам не дали в прошлый раз:
OutputAll 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
:
- cat everyother.txt
Вы видите тот же вывод, который вы видели на экране ранее:
OutputAll 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
по умолчанию не редактирует исходный файл, но вы можете изменить это поведение, передав параметр -i
, что означает «выполнять редактирование на месте». Это изменит исходный файл.
Предупреждение. При использовании ключа -i
исходный файл будет перезаписан, поэтому используйте его с осторожностью. Сначала выполните операции без переключателя -i
, а затем снова запустите команду с -i
, как только вы получите то, что хотите, создайте резервную копию исходного файла или перенаправьте вывод в файл. Очень легко случайно изменить исходный файл с помощью переключателя -i
.
Давайте попробуем отредактировать только что созданный файл everyother.txt
на месте. Давайте еще больше уменьшим файл, удалив каждую вторую строку
- sed -i '1~2d' everyother.txt
Если вы используете cat
для отображения файла с cat everyother.txt
, вы увидите, что файл был отредактирован.
Опция -i
может быть опасной. К счастью, sed
дает вам возможность создать резервную копию файла перед редактированием.
Чтобы создать файл резервной копии перед редактированием, добавьте расширение резервной копии сразу после параметра \-i:
- sed -i.bak '1~2d' everyother.txt
При этом создается файл резервной копии с расширением .bak
, а затем редактируется исходный файл на месте.
Далее вы узнаете, как использовать sed
для выполнения операций поиска и замены.
Замена текста
Возможно, наиболее известным применением sed
является замена текста. sed
может искать текстовые шаблоны с помощью регулярных выражений, а затем заменять найденный текст чем-то другим.
Вы можете узнать больше о регулярных выражениях, следуя статье Использование регулярных выражений Grep для поиска текстовых шаблонов в Linux.
В самой простой форме вы можете заменить одно слово на другое, используя следующий синтаксис:
's/old_word/new_word/'
s
является замещающей командой. Три косые черты (/
) используются для разделения различных текстовых полей. Вы можете использовать другие символы для разделения полей, если это будет более полезно.
Например, если вы пытаетесь изменить имя веб-сайта, будет полезно использовать другой разделитель, поскольку URL-адреса содержат косую черту.
Выполните следующую команду, чтобы напечатать URL-адрес с помощью echo
и изменить его с помощью sed
, используя символ подчеркивания (_
) в качестве разделителя:
- echo "http://www.example.com/index.html" | sed 's_com/index_org/home_'
Это заменяет com/index
на org/home
. Вывод показывает измененный URL:
Outputhttp://www.example.org/home.html
Не забудьте последний разделитель, иначе sed
будет жаловаться. Если вы выполнили эту команду:
- echo "http://www.example.com/index.html" | sed 's_com/index_org/home'
Вы увидите этот вывод:
Outputsed: -e expression #1, char 20: unterminated `s' command
Давайте создадим новый файл, чтобы попрактиковаться в некоторых заменах. Выполните следующую команду, чтобы создать новый текстовый файл с именем song.txt
:
- 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..." > song.txt
Теперь давайте заменим выражение on
на forward
. Используйте следующую команду:
- sed 's/on/forward/' song.txt
Вывод выглядит следующим образом:
Outputthis 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...
Здесь вы можете увидеть несколько примечательных вещей. Во-первых, sed
заменил шаблоны, а не слова. on
внутри song
изменяется на forward
.
Еще одна вещь, на которую следует обратить внимание, это то, что в строке 2 второй on
не был изменен на forward
.
Это связано с тем, что по умолчанию команда s
работает с первым совпадением в строке, а затем переходит к следующей строке. Чтобы заставить sed
заменить каждый экземпляр on
, а не только первый в каждой строке, вы должны передать необязательный флаг команде замены.
Предоставьте флаг g
команде подстановки, поместив его после набора подстановки:
- sed 's/on/forward/g' song.txt
Вы увидите этот вывод:
Outputthis 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...
Теперь команда замены изменяет каждый экземпляр.
Если вы только хотите изменить второй экземпляр \on, который sed находит в каждой строке, вы должны использовать номер 2
вместо g
:
- sed 's/on/forward/2' song.txt
На этот раз другие строки не изменились, так как у них нет второго вхождения:
Outputthis 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
, чтобы запретить автоматическую печать.
Затем вы можете передать параметр p
команде замены, чтобы вывести строки, в которых произошла замена.
- sed -n 's/on/forward/2p' song.txt
Строка, которая изменилась, выводится на экран:
Outputyes, it goes on and forward, my friend
Как видите, вы можете комбинировать флаги в конце команды.
Если вы хотите, чтобы процесс поиска игнорировал регистр, вы можете передать ему флаг \i.
- sed 's/SINGING/saying/i' song.txt
Вот результат, который вы увидите:
Outputthis 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/' song.txt
Вы увидите этот вывод:
OutputREPLACED 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...
Вы можете видеть, что подстановочное выражение соответствует от начала строки до последнего экземпляра at
.
Поскольку вы не знаете точную фразу, которая будет соответствовать строке поиска, вы можете использовать символ &
для представления совпадающего текста в строке замены.
Давайте поместим круглые скобки вокруг совпадающего текста:
- sed 's/^.*at/(&)/' song.txt
Вы увидите этот вывод:
Output(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/' song.txt
Вы увидите этот вывод:
Outputis 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...
Как видите, результаты не идеальны. Например, во второй строке пропускается первое слово, потому что оно содержит символ, не указанный в нашем наборе символов. Точно так же он интерпретировал yyll
как два слова в пятой строке.
Давайте улучшим регулярное выражение, чтобы оно было более точным:
- sed 's/\([^ ][^ ]*\) \([^ ][^ ]*\)/\2 \1/' song.txt
Вы увидите этот вывод:
Outputis 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
найдет текст хотя бы один раз, вы должны сопоставить его один раз без подстановочного знака, прежде чем использовать подстановочный знак.
Заключение
В этом руководстве вы изучили команду sed
. Вы печатали определенные строки из файла, искали текст, удаляли строки, перезаписывали исходный файл и использовали регулярные выражения для замены текста. Вы уже должны увидеть, как можно быстро преобразовать текстовый документ, используя правильно сконструированные команды sed.
В следующей статье этой серии вы познакомитесь с некоторыми дополнительными функциями.