У меня есть список файлов и соответствующих номеров строк, где я хочу выполнить замену:

s/LOG.error/LOG.warn

Есть и другие места, где это может произойти, и они не хотят нарушать эти линии. Как я могу сделать это, используя find и sed?

Файл отформатирован как:

FooBar.java 125
FooBar.java 180
FooBar2.java 128

Вот что я нашел, когда искал способ сделать это:

cat filenames.txt | xargs sed -i '<get-line-number-here>s/LOG.error/LOG.warn' <get-file-name-here>

1 ответ1

1

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

awk '$1 != prev { if (prev) print "\047 " prev;
    prev=$1;
    printf "sed -i \047" }
  { print $2 "s/LOG\\.error/LOG.warn/" }
  END { if (prev) print "\047 " prev }' filenames.txt | sh

Это быстрый и грязный хак, который сломается интересными и, возможно, опасными способами, если имена файлов в первом столбце не являются единым токеном.

Мы в основном преобразуем ваш текстовый файл в последовательность сценариев sed . Таким образом, ваш пример будет превращен в

sed -i '125s/LOG\.error/LOG.warn
180s/LOG\.error/LOG.warn/
' FooBar.java
sed -i '128s/LOG\.error/LOG.warn/
' FooBar2.java

которые вы заметите это sh скрипт , который содержит один sed для каждого файла.

Если вы работаете на платформе * BSD (включая Mac OS), вам нужно изменить sed -i на sed -i '' что в Awk будет "sed -i \047\047" , чтобы правильно вставлять одинарные кавычки, не мешая кавычки окружающей оболочки (так что вся строка становится printf "sed -i \047\047 \047" } (sic)).

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .