Используя только grep и sed, как мне заменить все вхождения:
a.example.com
с участием
b.example.com
в текстовом файле в дереве каталогов /home/user/, рекурсивно находя и заменяя все вхождения во всех файлах в подкаталогах.
Используя только grep и sed, как мне заменить все вхождения:
a.example.com
с участием
b.example.com
в текстовом файле в дереве каталогов /home/user/, рекурсивно находя и заменяя все вхождения во всех файлах в подкаталогах.
Попробуй это:
find /home/user/ -type f | xargs sed -i 's/a\.example\.com/b.example.com/g'
Если вы хотите игнорировать точечные каталоги
find . \( ! -regex '.*/\..*' \) -type f | xargs sed -i 's/a\.example\.com/b.example.com/g'
Изменить: экранированные точки в поисковом выражении
-name 'pattern' - где шаблон может быть похож на список доменов * - что-то, что сужает поиск.
- person Dennis Williamson; 18.10.2009
-print0 и -0 в find и xargs команды соответственно.
- person Mansoor Siddiqui; 30.07.2013
Попробуй это:
grep -rl 'SearchString' ./ | xargs sed -i 's/REPLACESTRING/WITHTHIS/g'
grep -rl будет рекурсивно искать SEARCHSTRING в каталогах ./ и заменять строки с помощью sed.
Ex:
Замена имени TOM на JERRY с использованием строки поиска как SWATKATS в каталоге CARTOONNETWORK
grep -rl 'SWATKATS' CARTOONNETWORK/ | xargs sed -i 's/TOM/JERRY/g'
Это заменит TOM на JERRY во всех файлах и подкаталогах в CARTOONNETWORK, где бы ни находилась строка SWATKATS.
Я знаю, что это действительно старый вопрос, но ...
Ответ @vehomzzz использует find и xargs, когда в вопросах явно указано только grep и sed.
@EmployedRussian и @BrooksMoses пытались сказать, что это дублирование awk и sed, но это не так - опять же, вопрос явно говорит grep и sed только.
Итак, вот мое решение, если вы используете Bash в качестве оболочки:
OLDIFS=$IFS
IFS=$'\n'
for f in `grep -rl a.example.com .` # Use -irl instead of -rl for case insensitive search
do
sed -i 's/a\.example\.com/b.example.com/g' $f # Use /gi instead of /g for case insensitive search
done
IFS=$OLDIFS
Если вы используете другую оболочку, такую как Unix SHell, дайте мне знать, и я постараюсь найти корректировку синтаксиса.
P.S .: Вот однострочный текст:
OLDIFS=$IFS;IFS=$'\n';for f in `grep -rl a.example.com .`;do sed -i 's/a\.example\.com/b.example.com/g' $f;done;IFS=$OLDIFS
Источники:
%, который не является обычным в URL-адресах, поэтому вам не нужно экранировать все косые черты.
- person dragon788; 02.04.2018
У меня работает следующая команда:
find /path/to/dir -name "file.txt" | xargs sed -i 's/string_to_replace/new_string/g'
если строка содержит косую черту «путь / к / каталогу», ее можно заменить другим символом для разделения, например «@» вместо «/».
Например: 's@string/to/replace@new/string@g'
На macOS у меня ни один из ответов не помог. Я обнаружил, что это произошло из-за различий в том, как sed работает в macOS и других системах BSD по сравнению с GNU.
В частности, BSD sed принимает параметр -i, но требует суффикс для резервной копии (но допускается пустой суффикс)
grep версия из этого ответа.
grep -rl 'foo' ./ | LC_ALL=C xargs sed -i '' 's/foo/bar/g'
find версия из этого ответа.
find . \( ! -regex '.*/\..*' \) -type f | LC_ALL=C xargs sed -i '' 's/foo/bar/g'
Не пропускайте Regex, чтобы игнорировать . папки, если вы используете репозиторий Git. Я понял это на собственном горьком опыте!
Этот LC_ALL=C параметр предназначен для того, чтобы избежать получения sed: RE error: illegal byte sequence, если sed находит последовательность байтов, которая не является допустимым символом UTF-8. Это еще одно различие между BSD и GNU. В зависимости от типа файлов, с которыми вы имеете дело, он может вам не понадобиться.
По какой-то непонятной для меня причине версия grep нашла больше вхождений, чем версия find, поэтому я рекомендую использовать grep.
Попробуйте эту команду:
/home/user/ directory - find ./ -type f \
-exec sed -i -e 's/a.example.com/b.example.com/g' {} \;
Мы можем попробовать использовать более мощный ripgrep как
rg "BYE_BYE_TEXT" ./ --files-with-matches | xargs sed -i "s/BYE_BYE_TEXT/WELCOME_TEXT/g"
Потому что ripgrep хорошо находит, а sed отлично заменяет.
rg продолжает использовать обратную косую черту, sed это не нравится (в основном их пропускает, поскольку в моем случае ни один из них не соответствует escape-коду, я думаю) и не работает с Нет такого файла или директории. Я мог sed заменить обратную реакцию на косую черту, но rg параметры в целом упростили бы задачу. На данный момент я использую rg "inpattern" ./ --files-with-matches | sed "s|\\\|/|g" | xargs sed -i -b "s/inpattern/outpattern/g" - (-b / двоичный режим, чтобы ваши окончания строк оставались такими, какие они есть).
- person mbx; 18.06.2021
Приведенная ниже команда выполнит рекурсивный поиск всех файлов, имя которых соответствует шаблону поиска, и заменит строку:
find /path/to/searchdir/ -name "serachpatter" -type f | xargs sed -i 's/stringone/StrIngTwo/g'
Также, если вы хотите ограничить глубину рекурсии, вы также можете установить ограничения:
find /path/to/searchdir/ -name "serachpatter" -type f -maxdepth 4 -mindepth 2 | xargs sed -i 's/stringone/StrIngTwo/g'
это намного проще.
for i in `find *` ; do sed -i -- 's/search string/target string/g' $i; done
find i => будет перебирать все файлы в папке и во вложенных папках.
sed -i => заменит в файлах соответствующую строку, если она существует.