Создать новую строку перед строкой, соответствующей шаблону, если еще нет новой строки - PullRequest
0 голосов
/ 27 августа 2018

У меня есть текстовый файл с несколькими строками. То, что я пытаюсь сделать, - это найти все строки, соответствующие шаблону, и, если перед ними нет символа новой строки (= непустая строка), создайте его. Как-то так, но это не работает должным образом:

sed -i '/[a-zA-Z0-9]/{N;/PATTERN/{s/PATTERN/\nPATTERN/}}' FILENAME

Я знаю, что это возможно сделать проще и лучше в awk или perl / bash, но я бы предпочел решение на одну строку / один шаг.

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

LINE1
LINE2
PATTERN
LINE3

PATTERN
LINE4

Ожидаемый результат:

LINE1
LINE2

PATTERN
LINE3

PATTERN
LINE4

Ответы [ 2 ]

0 голосов
/ 27 августа 2018

Взгляните на это GNU sed (обратите внимание, что awk - лучший инструмент для работы):

sed -i '/PATTERN/{x;/^$/!i\

x};h' input
  • h - это команда, которая сохраняет содержимое пространства паттернов в буфер хранения. Сохраняет строку в конце каждого цикла, чтобы ее можно было использовать в качестве «предыдущей» строки в следующем цикле

  • x обменивается содержимым пространств удержания и шаблона. Всякий раз, когда текущая строка совпадает с /PATTERN/, ранее сохраненная строка помещается в пространство шаблона. Если предыдущая строка NOT пуста (/^$/!), новая строка вставляется с помощью команды i. Затем текущая строка помещается обратно в пространство шаблона с помощью команды x

  • Если вы хотите добавить новую строку, даже если строка first соответствует /PATTERN/, используйте:

    sed -i '/PATTERN/{1h;x;/^$/! ...
    

Дальнейшее чтение:

0 голосов
/ 27 августа 2018

Я не очень хорош в sed, но вот как я это сделаю в awk:

awk 'prev != "" && /PATTERN/ { print "" } { prev = $0; print }' file

Если prev (предыдущая строка) не пуста, а текущая строка соответствует /PATTERN/, выведите пустую строку. Безоговорочно сохраните текущую строку для сравнения со следующей, и print текущую строку.

Чтобы выполнить редактирование на месте (например, sed -i), просто перенаправьте команду во временный файл, а затем перезапишите оригинал:

awk 'prev != "" && /PATTERN/ { print "" } { prev = $0; print }' file > tmp && mv tmp file

Обратите внимание, что, поскольку prev изначально не установлен, этот не будет печатать новую строку в начале вывода, даже если первая строка соответствует /PATTERN/. Чтобы обойти это, вы можете изменить условие на:

(NR == 1 || prev != "") && /PATTERN/

Вы также можете выполнить редактирование на месте с помощью GNU awk, используя опцию -i inplace.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...