Ваша идея использовать регекс-разделитель записей элегантна, но помните, что awk будет потреблять соответствующий текст, который в вашем случае будет первым не белым пробелом символа после записи.
Если ваша система имеет GNU версию awk, вы можете получить доступ к самой последней согласованной RS через переменную RT
, однако вам все равно нужно будет сохранить результат, чтобы зашивать его обратно в начало следующей записи - возможно, что-то вроде
gawk 'BEGIN{RS="\n[^[:blank:]]"}; {lastRT=RT}; /apollo/ {$0=substr(lastRT,2)""$0; print}' file.txt
Подложка (lastRT,2)
просто удаляет новую строку из совпадения, так что префиксом будет только символ без пробелов.
с awk и параметром
(файл filter.awk)
BEGIN { p=0 ; } # no printing
{ if ( (substr($0,1,1) != " ") && (substr($0,1,1) != "\t" ) ) p=0 ; # if no blank stop printing
if ( index($0,name) > 1 ) p=1 ; # pattern found ?
if (p) print ;
}
и результат
awk -v name=apollo -f filter.awk a.txt
com.apollo.apollonetworkcheck
1026ms running, 88 wakeups
88 alarms: flg=0x14
Я также бросаю perl на все, но иногда добавляю sed
для аромата:
$ sed 's/^\w/\n&/' file | perl -000ne 'print if /apollo/'
com.apollo.apollonetworkcheck
1026ms running, 88 wakeups
88 alarms: flg=0x14
sed
добавит дополнительную новую строку между каждой пластинкой. Он просто ищет строки, которые начинаются с буквенно-цифрового символа (^\w
) и заменяет этот символ на новую строку, а затем на сам символ (\n&
, &
означает "независимо от того, что вы только что сопоставили"). В результате получается файл, в котором записи выглядят как параграфы, перед ними пустая строка.
Теперь мы можем использовать "параграфный режим" на perl, активированный в -000
. В сочетании с -n
(считывание входной записи за записью) это позволяет нам прочитать всю запись сразу. Таким образом, достаточно вывести на печать текущую "линию" (запись), если она соответствует желаемому шаблону. В данном случае apollo
.
Я не уверен, насколько портативна нотация \w
. Если ваш sed
не может с этим справиться, используйте вместо этого:
sed 's/^[^ \t]/\n&/' file | perl -000ne 'print if /apollo/'
Вы также можете использовать тот же подход с awk
:
$ sed 's/^[^ \t]/\n&/' file | awk -v RS="\n\n" '/apollo/'
com.apollo.apollonetworkcheck
1026ms running, 88 wakeups
88 alarms: flg=0x14
Я всегда бросаю perl на все :-)
perl -ne 'if (/^\s/) { $x.=$_ }else{print $x if $x=~/apollo/; $x=$_} END {print $x if $x=~/apollo/}' file.txt
Правка: объяснение однострочности: