Вы также можете сделать это без print f :
awk 'BEGIN{ORS=""} {for(k=NF;k>0;--k) {print $k; if (k==1) print "\n"; else print " "}} ' file
Необходимо использовать буфер строк.
Попробуйте следующее:
awk -v N=4 -v pattern="example.*pattern" '{i=(1+(i%N));if (buffer[i]&& $0 ~ pattern) print buffer[i]; buffer[i]=$0;}' file
Установите значение N
на N-ю строку перед шаблоном для печати.
Установить значение шаблона
для регулярного выражения для поиска.
buffer
- это массив из N
элементов. Он используется для хранения строк. Каждый раз при нахождении шаблона печатается N
-я строка перед шаблоном.
Этот код не работает для предыдущих строк. Чтобы линии были перед совпадающим шаблоном, нужно как-то сохранить уже обработанные строки. Поскольку awk
имеет только ассоциативные массивы, я не могу придумать столь же простой способ сделать то, что вы хотите, в awk
, поэтому вот решение на perl:
perl -ne 'push @lines,$_; print $lines[0] if /PAT/; shift(@lines) if $.>LIM;' file
Изменить PAT
для шаблона, который вы хотите сопоставить, и LIM
для количества строк. Например, чтобы печатать 5-ю строку перед каждым появлением foo
, вы должны выполнить:
perl -ne 'push @lines,$_; print $lines[0] if /foo/; shift(@lines) if $.>5;' file
perl -ne
: прочитать входной файл построчно и применить данный сценарий по -e
в каждую строку. push @lines, $ _
: добавить текущую строку ( $ _
) в массив @lines
. print $ lines [0] if / PAT /
: распечатать первый элемент в массиве @lines
( $ lines [0]
), если текущая строка соответствует желаемый узор. shift (@lines), если $.> LIM;
: $.
- текущий номер строки. Если это больше предела, удалите 1-е значение из массива @lines
. В результате @lines
всегда будут иметь последние LIM
строк. tac file | awk 'c&&!--c;/pattern/{c=N}' | tac
Но здесь есть то же упущение, что и в случае использования «вперед», когда есть несколько совпадений в пределах N строк друг от друга.
И это не будет работать так хорошо, если входные данные будут переданы из запущенного процесса, но это самый простой способ, когда входной файл завершен и не увеличивается.
Альтернативный способ с sed
.
Для N = 1 :
sed '$!N; /.*\n.*pattern/P; D' FILE
Для N = 2
sed '1N; $!N; /.*\n.*\n.*pattern/P; D' FILE
Для случая N = 2 в первой строке будет указано следующее ] N-1 строк в пространстве шаблонов, затем запускает цикл N; P; D
- считывает еще одну строку и, если последняя строка в пространстве шаблонов совпадает, печатает первую строку в шаблоне пробел, затем удалите его, начав новый цикл.
Обратной стороной является то, что его необходимо изменить для разных значений N :
Для N = 3 :
sed '1{N;N}; $!N; /.*\n.*\n.*\n.*pattern/P; D' FILE
Для N = 4 ]:
sed '1{N;N;N}; $!N; /.*\n.*\n.*\n.*\n.*pattern/P; D' FILE
, поэтому он быстро становится громоздким, хотя для больших значений N вы можете подготовить файл сценария и передать его в sed
.