Unix: Поиск и замена во многих файлах одновременно

Задача: найти все файлы содержащие 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!

(отменить изменения во всех вкладках)

Ссылки по теме:

  1. VIM FAQ
  2. Save all open buffers at once
  3. Сохранение файла без прав на запись в vim используя sudo
  4. [SLUG] Vim. Search and replace in multiple files

Комментарии (5) на “Unix: Поиск и замена во многих файлах одновременно”

  1. это можно сделать и без вима…

    #!/bin/sh -e
    for fname in `find . -name «*» -print`;do; sed ‘s/OLDTEXT/NEWTEXT/g’ $fname > $fname.new && mv $fname.new $fname; done

  2. Alex Shatlovsky:

    shulc: Да, можно и так. Спасибо за дополнение.

  3. С помощью perl будет намного короче:
    perl -i -pe ‘s/OLD_TEXT/NEW_TEXT/;’ FILE_PATTERN.txt

    например:
    perl -i -pe ‘s/RSS/ATOM/;’ *.html
    заменит во всех html файлах подстроку «RSS» на «ATOM».

  4. Alex Shatlovsky:

    @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;»

  5. Dagrus:

    Так короче наверное )

    find . -name ‘*.txt’ -exec grep -ilH «OLD» {} ; | xargs sed -i -e «s/OLD/NEW/g»

Оставить комментарий