1

В каждом файле с именем файла, совпадающим с pattern1, я хочу найти строки, начинающиеся с pattern2, и добавить некоторую строку в новую строку над этими совпадающими строками.

В качестве простого примера предположим, что я рекурсивно ищу в файлах .txt картофель и хочу добавить «спам» выше, затем файл /tmp/blah.txt

hello
potato
world
not potato
bye

будет преобразован в

hello
spam
potato
world
not potato
bye

Похоже на простую работу для мастера оболочки, какой самый простой способ достичь этого? Я отметил некоторые из инструментов, которые, я думаю, были бы здесь обычными подозреваемыми, но я открыт для других предложений. Бонусные баллы, если он может показать мне предварительный просмотр различий, прежде чем я подтверждаю изменение файлов на месте.

2 ответа2

2

Лично я бы, вероятно, использовал Perl для чего-то подобного, но вы можете достичь того, чего хотите, только в bash:

while read -r line ; do if [[ $line =~ "potato" ]]; then echo spam;  fi;  echo $line; done < file.txt

Если вы хотите поместить результат в новый файл:

while read -r line ; do if [[ $line =~ "potato" ]]; then echo spam;  fi;  echo $line; done < file.txt > /tmp/outfile.txt
2

Я также сделал бы это в Perl:

$ for f in *txt; do perl -pne 'print "spam\n" if /^potato/' "$f"; done
hello
spam
potato
world
spam
not potato
bye

Флаг -p заставляет perl печатать каждую строку входного файла. -n означает "читать входной файл построчно" и применять скрипт, заданный -e к каждой строке. Затем сам скрипт будет печатать spam если текущая строка содержит potato и печатать каждую строку. Результатом будет строковый spam напечатанный над строками с potato .

Это просто распечатает новый файл без его изменения. Если вы хотите внести изменения в исходный файл, используйте -i:

$ for f in *txt; do perl -i.bak -pne 'print "spam\n" if /^potato/' "$f"; done

Это создаст файл резервной копии с именем foo.txt.bak для каждого обработанного файла и применит изменения к foo.txt .

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