
prova.txt
У меня есть такой файл :
Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random2
random3
random4
extra1
extra2
bla
Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561
extra2
bla
bla
Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random22131
и мне нужно grep out от "Start to grab here" до первой пустой строки. Вывод должен быть таким:
Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random2
random3
random4
Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561
Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random22131
Как вы видите, строки после «Start to grab here» случайны, поэтому флаг grep -A -B не работает:
cat prova.txt | grep "Start to grab from here" -A 15 | grep -B 15 "^$" > output.txt
Можете ли вы помочь мне найти способ, который перехватывает первую строку, которая будет захвачена (как "Начать захватывать отсюда"), до пустой строки. Я не могу предсказать, сколько случайных строк у меня будет после "Начать захватывать отсюда".
Приветствуется любое решение, совместимое с unix (grep, sed, awk лучше, чем perl или аналогичные).
ОТРЕДАКТИРОВАНО: после блестящего ответа @john1024 я хотел бы узнать, возможно ли:
1° сортируем блок (в соответствии с Начать захват отсюда: 1, затем 1, затем 2)
2° удалить 4 (в алфавитном порядке случайным образом) строки fix1,fix2,fix3,fix4, но их всегда 4
3° в конечном итоге удалить случайные дубликаты, например, команду sort -u
Окончательный результат должен быть таким:
# fix lines removed - match 1 first time
Start to grab from here: 1
random1
random2
random3
random4
#fix lines removed - match 1 second time
Start to grab from here: 1
#random1 removed cause is a dupe
random22131
#fix lines removed - match 2 that comes after 1
Start to grab from here: 2
random1546
random2561
или
# fix lines removed - match 1 first time and the second too
Start to grab from here: 1
random1
random2
random3
random4
#random1 removed cause is a dupe
random22131
#fix lines removed - match 2 that comes after 1
Start to grab from here: 2
random1546
random2561
Второй вывод лучше первого. Нужна какая-то другая магия команд unix.
решение1
Использование awk
Пытаться:
$ awk '/Start to grab/,/^$/' prova.txt
Start to grab from here: 1
random1
random2
random3
random4
Start to grab from here: 2
random1546
random2561
Start to grab from here: 3
random45
random22131
/Start to grab/,/^$/
определяет диапазон. Он начинается с любой строки, которая соответствует Start to grab
, и заканчивается первой пустой строкой, ^$
которая следует за ним.
Использование sed
С очень похожей логикой:
$ sed -n '/Start to grab/,/^$/p' prova.txt
Start to grab from here: 1
random1
random2
random3
random4
Start to grab from here: 2
random1546
random2561
Start to grab from here: 3
random45
random22131
-n
сообщает sed, что не нужно ничего печатать, пока мы явно не попросим его об этом. /Start to grab/,/^$/p
сообщает ему, что нужно печатать все строки в диапазоне, определенном /Start to grab/,/^$/
.
решение2
Я публикую альтернативное решение, так как оно может быть полезным для некоторых случаев использования. Это решение не совсем соответствует заявленным требованиям, для лучшего решения см. ответ от @John1024.
Вы можете использовать awk, установив разделитель записей на пустую строку, awk будет интерпретировать это как пустые символы новой строки:
$ awk '/Start/' RS= prova.txt
Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random2
random3
random4
Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561
Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random22131
Эта версия не сохраняет пустые новые строки в выводе. Она также покажет контекст перед совпадением, если оно есть. Такое поведение может быть очень полезным при поиске чего-либо в файле, и вы хотите увидеть блок с разделителями новой строки, частью которого он является, например:
$ awk '/random1546/' RS= prova.txt
Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561
Например, я нахожу это полезным при поиске чего-либо в ini
файлах.