Как использовать sed для поиска и замены строки в файлах

How to Use sed to Find and Replace String in Files

11 Апреля 2020 | Терминал

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

Как использовать sed для поиска и замены строки в файлах

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

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


Найти и заменить строку на sed

Существует несколько версий sed, с некоторыми функциональными различиями между ними. macOS использует версию BSD, и большинство дистрибутивов Linux поставляются с sedпредварительно установленной GNU по умолчанию. Мы будем использовать версию GNU.

Общая форма поиска и замены текста sed принимает следующую форму:


sed -i 's/SEARCH_REGEX/REPLACEMENT/g' INPUTFILE

  • -i- По умолчанию sed записывает свой вывод на стандартный вывод. Эта опция говорит sed редактировать файлы на месте. Если указано расширение (например, -i.bak), будет создана резервная копия исходного файла.
  • s - Команда замены, вероятно, наиболее используемая команда в sed.
  • / / /- разделитель персонажа. Это может быть любой символ, но обычно используется /символ косой черты ( ).
  • SEARCH_REGEX - Обычная строка или регулярное выражение для поиска.
  • REPLACEMENT - Строка замены.
  • g- Глобальный флаг замены. По умолчанию sedфайл читает построчно и изменяет только первое вхождение SEARCH_REGEXстроки. Если указан флаг замены, все случаи будут заменены.
  • INPUTFILE - Имя файла, для которого вы хотите выполнить команду.

Хорошей практикой является размещение кавычек вокруг аргумента, чтобы метасимволы оболочки не расширялись.

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

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

file.txt
123 Foo foo foo 
foo /bin/bash Ubuntu foobar 456

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

sed -i 's/foo/linux/' file.txt
123 Foo linux foo 
linux /bin/bash Ubuntu foobar 456

С глобальным флагом замены sed заменяет все вхождения шаблона поиска:

sed -i 's/foo/linux/g' file.txt
123 Foo linux linux
linux /bin/bash Ubuntu linuxbar 456

Как вы могли заметить, в предыдущем примере подстрока foo внутри foobar строки также заменяется. Если это нежелательное поведение, используйте выражение word-boundery ( \b) на обоих концах строки поиска. Это гарантирует, что отдельные слова не совпадают.

sed -i 's/\bfoo\b/linux/g' file.txt
123 Foo linux linux
linux /bin/bash Ubuntu foobar 456

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

sed -i 's/foo/linux/gI' file.txt
123 linux linux linux 
linux /bin/bash Ubuntu linuxbar 456

Если вы хотите найти и заменить строку, содержащую символ-разделитель ( /), вам нужно использовать обратную косую черту ( \), чтобы избежать косой черты. Например , чтобы заменить /bin/bashс /usr/bin/zsh вы будете использовать

sed -i 's/\/bin\/bash/\/usr\/bin\/zsh/g' file.txt

Более простой и читаемый вариант - использовать другой символ-разделитель. Большинство людей используют вертикальную черту ( |) или двоеточие ( :), но вы можете использовать любой другой символ:

sed -i 's|/bin/bash|/usr/bin/zsh|g' file.txt
123 Foo foo foo 
foo /usr/bin/zsh Ubuntu foobar 456

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

sed -i 's/\b[0-9]\{3\}\b/number/g' file.txt
number Foo foo foo 
foo /bin/bash demo foobar number


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

Например, если вы хотите добавить фигурные скобки {}вокруг каждого трехзначного числа, введите:

sed -i 's/\b[0-9]\{3\}\b/{&}/g' file.txt
{123} Foo foo foo 
foo /bin/bash demo foobar {456}


   И последнее, но не менее важное: всегда полезно сделать резервную копию при редактировании файла с помощью sed. Для этого просто предоставьте расширение -i опции. Например, чтобы отредактировать file.txt и сохранить исходный файл, как file.txt.bak вы бы использовали:

sed -i.bak 's/foo/linux/g' file.txt


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

ls
file.txt file.txt.bak

Рекурсивный поиск и замена 

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

Следующая команда будет рекурсивно искать файлы в текущем рабочем каталоге и передавать имена файлов в sed.

find . -type f -exec sed -i 's/foo/bar/g' {} +


   Чтобы избежать проблем с файлами, содержащими пробел в их именах, используйте -print0 опцию, которая указывает findпечатать имя файла, за которым следует нулевой символ и направлять вывод в sedиспользование xargs -0:

find . -type f -print0 | xargs -0 sed -i 's/foo/bar/g'

Чтобы исключить каталог, используйте -not -path опцию. Например, если вы заменяете строку в локальном git-репо, чтобы исключить все файлы, начинающиеся с точки ( .), используйте:

find . -type f -not -path '*/\.*' -print0 | xargs -0 sed -i 's/foo/bar/g'


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

find . -type f -name "*.md" -print0 | xargs -0 sed -i 's/foo/bar/g'


   Другой вариант - использовать grep команду для рекурсивного поиска всех файлов, содержащих шаблон поиска, а затем передать имена файлов по адресу sed:

grep -rlZ 'foo' . | xargs -0 sed -i.bak 's/foo/bar/g'

Вывод

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

Чтобы узнать о более sedкоманд, опции и флаги посетить GNU СЭД руководство и Grymoire СЭД учебник


    Комментарии

    Если у вас есть вопросы, не стесняйтесь оставлять комментарии ниже.

Загрузка комментариев...