
При работе с текстовыми файлами вам часто приходится находить и заменять строки текста в одном или нескольких файлах.
sed — потоковый редактор . Он может выполнять базовые операции с текстом в файлах и входных потоках, таких как конвейеры. С помощью sed можно искать, находить и заменять, вставлять и удалять слова и строки. Он поддерживает базовые и расширенные регулярные выражения, позволяющие сопоставлять сложные шаблоны.
В этой статье мы расскажем, как искать и заменять строки с помощью sed . Мы также покажем, как выполнять рекурсивный поиск и замену.
Найти и заменить строку с помощью sed
Существует несколько версий sed , которые имеют некоторые функциональные различия. В macOS используется версия BSD, в то время как в большинстве дистрибутивов Linux по умолчанию предустановлен GNU sed . Мы будем использовать версию 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 для поиска и замены текста в файлах с некоторыми из ее наиболее часто используемых параметров и флагов.
Для демонстрации мы будем использовать следующий файл:
файл.txt
123 Foo foo foo foo /bin/bash Ubuntu foobar 456
Если флаг g опущен, заменяется только первый экземпляр искомой строки в каждой строке:
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 также заменяется в предыдущем примере. Если это нежелательно, используйте выражение, ограничивающее слова ( b ), на обоих концах строки поиска. Это гарантирует, что части слов не будут найдены.
sed -i 's/bfoob/linux/g' file.txt
123 Foo linux linux linux /bin/bash Ubuntu foobar 456
Чтобы сделать сопоставление с шаблоном нечувствительным к регистру, используйте флаг I В примере ниже мы используем оба флага: g и 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
Вы также можете использовать регулярные выражения. Например, чтобы найти все трёхзначные числа и заменить их 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
Рекурсивный поиск и замена
Иногда может потребоваться рекурсивно найти в каталогах файлы, содержащие строку, и заменить её во всех файлах. Это можно сделать с помощью таких команд, как find или 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 sed и учебник Grymoire sed .
Если у вас есть вопросы или пожелания, не стесняйтесь оставлять комментарии.
Связанные руководства