Я намагаюся знайти та замінити рядок у всіх файлах, що відповідають grep:
grep -n 'foo' *
дасть мені результат у вигляді:
[filename]:[line number]:[text]
Для кожного файлу, що повертається grep, я хотів би змінити файл, замінивши foo
на bar
.
Я намагаюся знайти та замінити рядок у всіх файлах, що відповідають grep:
grep -n 'foo' *
дасть мені результат у вигляді:
[filename]:[line number]:[text]
Для кожного файлу, що повертається grep, я хотів би змінити файл, замінивши foo
на bar
.
Відповіді:
Ви маєте на увазі пошук і заміну рядка у всіх файлах, що відповідають grep?
perl -p -i -e 's/oldstring/newstring/g' `grep -ril searchpattern *`
Редагувати
Оскільки це, здається, досить популярне питання, яке я думав би оновити.
Сьогодні я в основному використовую, ack-grep
оскільки це більш зручно для користувачів. Отже, наведена вище команда буде такою:
perl -p -i -e 's/old/new/g' `ack -l searchpattern`
Для обробки пробілів в іменах файлів ви можете запустити:
ack --print0 -l searchpattern | xargs -0 perl -p -i -e 's/old/new/g'
ви можете зробити більше ack-grep
. Скажімо, ви хочете обмежити пошук лише файлами HTML:
ack --print0 --html -l searchpattern | xargs -0 perl -p -i -e 's/old/new/g'
І якщо пробіли не є проблемою, це ще коротше:
perl -p -i -e 's/old/new/g' `ack -l --html searchpattern`
perl -p -i -e 's/old/new/g' `ack -f --html` # will match all html files
Здається, це те, що ви хочете, виходячи з прикладу, який ви дали:
sed -i 's/foo/bar/g' *
Він не є рекурсивним (він не потраплятиме в підкаталоги). Для хорошого рішення заміни вибраних файлів у дереві я б використав find:
find . -name '*.html' -print -exec sed -i.bak 's/foo/bar/g' {} \;
Це *.html
вираз, якому повинні збігатися файли, .bak
після -i
створення копії оригінального файлу з розширенням .bak (це може бути будь-яке розширення, яке вам подобається), а g
в кінці виразу sed вказує sed замінити кілька копій на один рядок (а не лише перший). -print
Знайти це зручність для показу , які файли були узгоджені. Все це залежить від точних версій цих інструментів у вашій системі.
find
команді каталог для запуску, наприклад find . -name '*.html'
або find directoryname/ -name '*'
.
sed -ie 's/foo/bar/g' *
Якщо у вас sed(1)
є -i
можливість, використовуйте її так:
for i in *; do
sed -i 's/foo/bar/' $i
done
Якщо ні, є кілька способів варіацій наведених нижче, залежно від того, з якою мовою ви хочете грати:
ruby -i.bak -pe 'sub(%r{foo}, 'bar')' *
perl -pi.bak -e 's/foo/bar/' *
for i in *; do ...
є зайвим, sed може взяти список файлів як аргументи.
for i in *; do; sed -i 's/foo/bar/g' "$i"; done
Мені подобається та використовується вищезазначене рішення або загальносистемний пошук та заміна серед тисяч файлів:
find -name '*.htm?' -print -exec sed -i.bak 's/foo/bar/g' {} \;
Я припускаю, що з '* .htm?' замість .html здійснює пошук і знаходження файлів .htm та .html однаково.
Я замінюю .bak на більш загальносистемну тильду (~), щоб полегшити очищення файлів резервних копій.
Це працює за допомогою grep без необхідності використовувати perl або find.
grep -rli 'old-word' * | xargs -i@ sed -i 's/old-word/new-word/g' @
-i
що не працює для інших ОС. Працює у мене на ubuntu.
xargs
(на Ubuntu) каже, що -i
застаріла та використовується -I
замість неї. Отже, слід сказати:grep -rli 'old-word' * | xargs -I filepath sed -i 's/old-word/new-word/g' filepath
find . -type f -print0 | xargs -0 <sed/perl/ruby cmd>
буде обробляти кілька імен файлів, що містять пробіл, одночасно завантажуючи по одному інтерпретатору за партію. Набагато швидше.
Відповідь, вже дана за допомогою find та sed
find -name '*.html' -print -exec sed -i.bak 's/foo/bar/g' {} \;
це, мабуть, стандартна відповідь. Або ви можете використовувати perl -pi -e s/foo/bar/g'
замість sed
команди.
Для більшості швидких застосувань команда rpl легше запам'ятовується. Ось заміна (foo -> bar), рекурсивно для всіх файлів у поточному каталозі:
rpl -R foo bar .
Він не доступний за замовчуванням у більшості дистрибутивів Linux, але швидко встановлюється ( apt-get install rpl
або подібний).
Однак для більш жорстких завдань, які передбачають регулярні вирази та зворотну заміну, або перейменування файлів, а також пошук та заміну, найзагальнішим та найпотужнішим інструментом, який я знаю, є repren , невеликий скрипт Python, який я писав деякий час тому для деяких торнірські завдання перейменування та рефакторингу. Причини, за якими ви можете віддати перевагу:
Перевірте README для прикладів.
Це насправді простіше, ніж здається.
grep -Rl 'foo' ./ | xargs -n 1 -I % sh -c "ls %; sed -i 's/foo/bar/g' %";
Простенька. Якщо ви добре зрозумієте find, grep, xargs, sed та awk, майже нічого неможливого не стосується маніпуляцій з текстовими файлами в bash :)
Can't open Untitled: No such file or directory, <> line 5
при спробі "Без назви папка / файл.txt".