Задача: найти все файлы содержащие OLDTEXT, и заменить OLDTEXT на NEWTEXT.
UPD2:Решение, предложенное ocehb:
grep -rl OLDTEXT . | grep -Ev '(~|.o|.a)$' | grep -Ev '/.svn/' | xargs perl -i -pe "s/OLD_TEXT/NEW_TEXT/g;"
UPD1:Вариант без vim:
grep -HR OLDTEXT ./ | awk '{print $1}' | sed 's/:.*$//' | grep -v '~' | sort | uniq | xargs perl -i -pe "s/OLD_TEXT/NEW_TEXT/g;"
Изначально предложенное решение с vim:
grep -HR OLDTEXT ./ | awk '{print $1}' | sed 's/:.*$//' | grep -v '~' | sort | uniq | xargs vim -p
В открывшемся окне vim
командуем:
:tabdo %s/OLDTEXT/NEWTEXT/g
(заменить OLDTEXT на NEWTEXT во всех вкладках)
:xa
(записать изменения во всех вкладках)
либо
:qa!
(отменить изменения во всех вкладках)
Ссылки по теме:
это можно сделать и без вима…
#!/bin/sh -e
for fname in `find . -name «*» -print`;do; sed ‘s/OLDTEXT/NEWTEXT/g’ $fname > $fname.new && mv $fname.new $fname; done
shulc: Да, можно и так. Спасибо за дополнение.
С помощью perl будет намного короче:
perl -i -pe ‘s/OLD_TEXT/NEW_TEXT/;’ FILE_PATTERN.txt
например:
perl -i -pe ‘s/RSS/ATOM/;’ *.html
заменит во всех html файлах подстроку «RSS» на «ATOM».
@ehles:
Согласен, так короче. Но:
1) Нужен модификатор /g для глобальный замены, а не только первого найденного в каждой строке фрагмента, т.е.
$ perl -i -pe ’s/OLD_TEXT/NEW_TEXT/g;’ FILE_PATTERN.txt
2) glob’ы не рулят :) Лучше использовать find:
$ find ./ -type f -name «*.html» -exec perl -i -pe «s/OLD_TEXT/NEW_TEXT/g;» {} \;
3) Чтобы не модифицировать файлы без искомой подстроки, можно-таки предварительно отобрать нужные:
grep -HR OLDTEXT ./ | awk ‘{print $1}’ | sed ‘s/:.*$//’ | grep -v ‘~’ | sort | uniq | xargs perl -i -pe «s/OLD_TEXT/NEW_TEXT/g;»
Так короче наверное )
find . -name ‘*.txt’ -exec grep -ilH «OLD» {} ; | xargs sed -i -e «s/OLD/NEW/g»
По-моему, более vim-овский способ такой.
Имеем: много файлов *.html, лежащих в одной папке.
Надо: поменять OLD на NEW во всех файлах.
:args ../*.html
:argdo %s/OLD/NEW/ge | update
Вот и всё.
В моём случае OLD представляло собой очень большую многострочную конструкцию, и я был чрезвычайно рад, когда нашёл способ сообщить о ней vim-у:
:argdo %s/OLD-begin\_.*OLD-end/\[email protected]/ge | update
OLD-begin — начало заменяемого фрагмента, OLD-end — окончание заменяемого фрагмента, причём неважно, сколько и какого текста между ними, конструкция \_.* допускает между ними возвраты каретки.
\[email protected] здесь написано вместо NEW, потому как вставляемая конструкция тоже была многострочной и просто была скопирована в регистр ‘n’.