Использование sed и grep/egrep для поиска и замены

Я использую egrep -R, за которым следует регулярное выражение, содержащее около 10 объединений, так что: .jpg | .png | .gif и т.д. Это хорошо работает, теперь я хотел бы заменить все строки, найденные с помощью .bmp

Я думал о чем-то вроде

egrep -lR "\.jpg|\.png|\.gif" . | sed "s/some_expression/.jpg/" file_it_came_form

так что проблема здесь в том, как я могу сделать аналогичное регулярное выражение union в sed и как я могу сказать, что он сохранил изменения в файле, из которого он получил вход.

Ответ 1

Используйте эту команду:

egrep -lRZ "\.jpg|\.png|\.gif" . \
    | xargs -0 -l sed -i -e 's/\.jpg\|\.gif\|\.png/.bmp/g'
  • egrep: найти совпадающие строки с использованием расширенных регулярных выражений

    • -l: только список совпадающих имен файлов

    • -R: искать рекурсивно через все указанные каталоги

    • -Z: используйте \0 в качестве разделителя записей

    • "\.jpg|\.png|\.gif": сопоставить одну из строк ".jpg", ".gif" или ".png"

    • .: запустите поиск в текущем каталоге

  • xargs: выполните команду со стандартным аргументом stdin

    • -0: используйте \0 в качестве разделителя записей. Это важно, чтобы соответствовать -Z egrep и избегать обмана местами и символами новой строки во входных именах файлов.

    • -l: используйте одну строку для каждой команды в качестве параметра

  • sed: s текст ed итор

    • -i: замените входной файл на выход без создания резервной копии

    • -e: используйте следующий аргумент как выражение

    • 's/\.jpg\|\.gif\|\.png/.bmp/g': замените все вхождения строк ".jpg", ".gif" или ".png" на ".bmp"

Ответ 2

Честно говоря, как я обожаю sed для выполнения соответствующих задач, это определенно задача для perl - это действительно более мощная для такого типа однострочных, особенно для "записи обратно туда, где она исходит" (perl -i для вас, и, возможно, также позволяет сохранить старую версию, например, с добавлением .bak, просто используйте -i.bak).

perl -i.bak -pe 's/\.jpg|\.png|\.gif/.jpg/

вместо сложной работы в sed (если возможно, там) или awk...

Ответ 3

Другой способ сделать это

find . -name *.xml -exec sed -i "s/4.6.0-SNAPSHOT/5.0.0-SNAPSHOT/" {} \;

Некоторая помощь в отношении указанной команды

Поиск найдет для вас в текущем каталоге, обозначенном .

-name имя файла в моем случае его pom.xml может давать дикие карты.

-exec выполнить

sed редактор потока

-i игнорировать регистр

s для замены

/4.6.0.../ Строка для поиска

/5.0.0.../ Строка, которую нужно заменить

Ответ 4

Я не мог заставить какие-либо команды на этой странице работать для меня: sed решение добавило новую строку в конец всех обработанных файлов, и perl-решение не смогли принять достаточное количество аргументов из find. Я нашел это решение, которое отлично работает:

find . -type f -name '*.[hm]' -print0 
    | xargs -0 perl -pi -e 's/search_regex/replacement_string/g'

Это восстановит текущее дерево каталогов и заменит search_regex на replacement_string в любых файлах, заканчивающихся на .h или .m.

Я также использовал rpl для этой цели в прошлом.

Ответ 5

попробуйте что-то, используя цикл for

 for i in `egrep -lR "YOURSEARCH" .` ; do echo  $i; sed 's/f/k/' <$i >/tmp/`basename $i`; mv /tmp/`basename $i` $i; done

не очень, но должен делать.

Ответ 6

Моим вариантом использования я хотел заменить foo:/Drive_Letter с foo:/bar/baz/xyz В моем случае я смог сделать это со следующим кодом. Я был в том же каталоге, где было большое количество файлов.

find . -name "*.library" -print0 | xargs -0 sed -i '' -e 's/foo:\/Drive_Letter:/foo:\/bar\/baz\/xyz/g'

надеюсь, что это помогло.

UPDATE s | foo:/Drive_letter: | foo:/ba/baz/xyz | g