Поиск по сайту:

Основы использования редактора 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 будет выводить вывод на экран, а не сохранять его в файл.

Основное использование:

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

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

  1. cd
  2. cp /usr/share/common-licenses/BSD .

Если у вас нет локальной копии лицензии BSD, создайте ее самостоятельно с помощью этой команды:

  1. cat << 'EOF' > BSD
  2. Copyright (c) The Regents of the University of California.
  3. All rights reserved.
  4. Redistribution and use in source and binary forms, with or without
  5. modification, are permitted provided that the following conditions
  6. are met:
  7. 1. Redistributions of source code must retain the above copyright
  8. notice, this list of conditions and the following disclaimer.
  9. 2. Redistributions in binary form must reproduce the above copyright
  10. notice, this list of conditions and the following disclaimer in the
  11. documentation and/or other materials provided with the distribution.
  12. 3. Neither the name of the University nor the names of its contributors
  13. may be used to endorse or promote products derived from this software
  14. without specific prior written permission.
  15. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  16. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  19. FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  21. OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  23. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  24. OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  25. SUCH DAMAGE.
  26. EOF

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

  1. sed '' BSD

Вы увидите лицензию BSD, отображаемую на экране:

Output
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 выводил каждую полученную строку на стандартный вывод.

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

  1. cat BSD | sed ''

Вы увидите вывод файла:

Output
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 без каких-либо операций, будут выводить результаты непосредственно на стандартный вывод.

Давайте рассмотрим явную команду print в sed, которую вы указываете с помощью символа p в одинарных кавычках.

Выполните следующую команду:

  1. sed 'p' BSD

Вы увидите, что каждая строка файла BSD напечатана дважды:

Output
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 автоматически печатает каждую строку по умолчанию, а затем вы указали ему печатать строки явно с помощью команды \p, поэтому вы печатаете каждую строку дважды.

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

Вы можете очистить результаты, передав параметр -n в sed, который подавляет автоматическую печать:

  1. sed -n 'p' BSD
Output
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 напечатает первую строку файла. Выполните следующую команду:

  1. sed -n '1p' BSD

Первая строка выводит на экран:

Output
Copyright (c) The Regents of the University of California.

Поместив число 1 перед командой печати, вы указали sed номер строки, с которой нужно работать. С таким же успехом можно вывести пять строк (не забудьте \-n):

  1. sed -n '1,5p' BSD

Вы увидите этот вывод:

Output
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 напечатать строки с 1 по 5. Вы могли бы указать это по-другому, указав первый адрес, а затем используя смещение, чтобы сообщить sed, сколько дополнительных строк нужно пройти, например:

  1. sed -n '1,+4p' BSD

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

Если вы хотите печатать каждую вторую строку, укажите интервал после символа ~. Следующая команда печатает каждую вторую строку в файле BSD, начиная со строки 1:

  1. sed -n '1~2p' BSD

Вот результат, который вы увидите:

Output
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 . . . . . .

Вы также можете использовать sed для удаления текста из вывода.

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

Вы можете выполнить удаление текста там, где ранее указывали печать текста, заменив команду p на команду d.

В этом случае вам больше не нужна команда -n, потому что sed напечатает все, что не удалено. Это поможет вам увидеть, что происходит.

Измените последнюю команду из предыдущего раздела, чтобы сделать ее

  1. sed '1~2d' BSD

В результате вы видите каждую строку, которую вам не дали в прошлый раз:

Output
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. . . . . . .

Здесь важно отметить, что наш исходный файл не затрагивается. Он все еще цел. Изменения выводятся на наш экран.

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

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

Теперь откройте файл с помощью cat:

  1. cat everyother.txt

Вы видите тот же вывод, который вы видели на экране ранее:

Output
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 по умолчанию не редактирует исходный файл, но вы можете изменить это поведение, передав параметр -i, что означает «выполнять редактирование на месте». Это изменит исходный файл.

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

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

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

Если вы используете cat для отображения файла с cat everyother.txt, вы увидите, что файл был отредактирован.

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

Чтобы создать файл резервной копии перед редактированием, добавьте расширение резервной копии сразу после параметра \-i:

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

При этом создается файл резервной копии с расширением .bak, а затем редактируется исходный файл на месте.

Далее вы узнаете, как использовать sed для выполнения операций поиска и замены.

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

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

Вы можете узнать больше о регулярных выражениях, следуя статье Использование регулярных выражений Grep для поиска текстовых шаблонов в Linux.

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

's/old_word/new_word/'

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

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

Выполните следующую команду, чтобы напечатать URL-адрес с помощью echo и изменить его с помощью sed, используя символ подчеркивания (_) в качестве разделителя:

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

Это заменяет com/index на org/home. Вывод показывает измененный URL:

Output
http://www.example.org/home.html

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

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

Вы увидите этот вывод:

Output
sed: -e expression #1, char 20: unterminated `s' command

Давайте создадим новый файл, чтобы попрактиковаться в некоторых заменах. Выполните следующую команду, чтобы создать новый текстовый файл с именем song.txt:

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

Теперь давайте заменим выражение on на forward. Используйте следующую команду:

  1. sed 's/on/forward/' song.txt

Вывод выглядит следующим образом:

Output
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...

Здесь вы можете увидеть несколько примечательных вещей. Во-первых, sed заменил шаблоны, а не слова. on внутри song изменяется на forward.

Еще одна вещь, на которую следует обратить внимание, это то, что в строке 2 второй on не был изменен на forward.

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

Предоставьте флаг g команде подстановки, поместив его после набора подстановки:

  1. sed 's/on/forward/g' song.txt

Вы увидите этот вывод:

Output
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...

Теперь команда замены изменяет каждый экземпляр.

Если вы только хотите изменить второй экземпляр \on, который sed находит в каждой строке, вы должны использовать номер 2 вместо g:

  1. sed 's/on/forward/2' song.txt

На этот раз другие строки не изменились, так как у них нет второго вхождения:

Output
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, чтобы запретить автоматическую печать.

Затем вы можете передать параметр p команде замены, чтобы вывести строки, в которых произошла замена.

  1. sed -n 's/on/forward/2p' song.txt

Строка, которая изменилась, выводится на экран:

Output
yes, it goes on and forward, my friend

Как видите, вы можете комбинировать флаги в конце команды.

Если вы хотите, чтобы процесс поиска игнорировал регистр, вы можете передать ему флаг \i.

  1. sed 's/SINGING/saying/i' song.txt

Вот результат, который вы увидите:

Output
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, используйте следующую команду:

  1. sed 's/^.*at/REPLACED/' song.txt

Вы увидите этот вывод:

Output
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...

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

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

Давайте поместим круглые скобки вокруг совпадающего текста:

  1. 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 и так далее.

В этом примере мы поменяем местами первые два слова каждой строки:

  1. sed 's/\([a-zA-Z0-9][a-zA-Z0-9]*\) \([a-zA-Z0-9][a-zA-Z0-9]*\)/\2 \1/' song.txt

Вы увидите этот вывод:

Output
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...

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

Давайте улучшим регулярное выражение, чтобы оно было более точным:

  1. sed 's/\([^ ][^ ]*\) \([^ ][^ ]*\)/\2 \1/' song.txt

Вы увидите этот вывод:

Output
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 найдет текст хотя бы один раз, вы должны сопоставить его один раз без подстановочного знака, прежде чем использовать подстановочный знак.

Заключение

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

В следующей статье этой серии вы познакомитесь с некоторыми дополнительными функциями.