Недавно в OpenSuse -скользящий выпуск Tumbleweed установил LTO на gcc9 для своих сборок.http://hubicka.blogspot.com/2019/05/gcc-9-link-time-and-inter-procedural.html
Использование awk:
awk '/====/{ buf=""; c=0; found=1; next }
++c<=2 { buf=(buf==""?"":buf ORS) $0 }
END{ if(c>=2 && found)print buf }' infile
Вход:
====
1
2
3
4
====
11
22
33
====
111
222
333
444
====
1111
2222
3333
Выход:
1111
2222
Используя sed
и предполагая, что вам нужны две строки после последнего совпаденияpattern
(и дополнительно предполагая, что каждая строка, соответствующая pattern
, отделена как минимум двумя строками от любой другой совпадающей строки):
$ cat file
a
b pattern
c the 1st
d the 2nd
e the 3rd
1
2
3 pattern
4 the first
5 the second
6 the third
7
$ sed -n -e '/pattern/ { n; N; h; }' -e '$ { g; /./p; }' file
4 the first
5 the second
Команда sed
считывает следующую строку с n
при совпадении pattern
.Строка после этого добавляется в буфер с N
и обе строки копируются в пространство хранения сh
(поверх -с записью всего, что раньше хранилось там ).
Когда мы доходим до последней строки, мы получаем пространство хранения, которое теперь содержит две самые последние строки после строки, совпадающей с pattern
, или пусто, если не совпадало pattern
. Если буфер не пуст, он выводится.
Чтобы получить три строки после строки, соответствующей pattern
, используйте n; N; N; h;
вместо n; N; h;
.
Получение трех строк после сопоставления строкpattern
(теперь предполагается, что совпадающие строки разделены не менее чем тремя строками):
$ sed -n -e '/pattern/ { n; N; N; h; }' -e '$ { g; /./p; }' file
4 the first
5 the second
6 the third
Устранение необходимости в том, чтобы строки, соответствующие pattern
, находились далеко друг от друга, нам нужно проверить, соответствует ли какая-либо из «строк после» pattern
при их чтении, и если это так, перезапустить оттуда.
sed -n -e ':a' -e '/pattern/ { n; /pattern/ba; N; /pattern/ba; h; }' -e '$ { x; /./p; }' file
Вы можете использоватьed
:
printf '%s\n' '?pattern?+1, ?pattern?+2 p' | ed -s file
Это отправляет одну команду на ed
на стандартный ввод; флаг -s
запрещает подсчет байта -в качестве вывода при чтении файла. Команда ломается следующим образом:
...,... p
--вывести строки в заданном (...,... )диапазоне адресов ?pattern?+1
--выполнить поиск pattern
в обратном направлении, затем добавить один ?pattern?+2
--выполнить поиск pattern
в обратном направлении, затем добавить два Текущим значением по умолчанию является последняя строка файла, поэтому при поиске будет найдено последнее вхождение pattern
в файле. Затем смещения выбирают две следующие строки.
Используя GNU grep
и tail
и пример файла αғsнιη:
$ cat file
====
1
2
3
4
====
11
22
33
====
111
222
333
444
====
1111
2222
3333
$ grep -A2 "====" file | tail -n2
1111
2222
-A2
указывает grep
напечатать соответствующую строку (, в данном случае мы ищем====
)и две строки после нее. Затем tail -n2
печатает только две последние строки.
Если ваш файл очень большой, вы можете ускорить его, читая с конца файла с помощью tac
и обращая логику:
$ tac file | grep -m1 -B2 "====" | tac |tail -n2
1111
2222
Использование awk:
awk '{ arr[NR]=$0; if ($0 ~ /====/) line=NR}END{if (line) for(i=line+1;i<=line+2;i++) print arr[i]}' file
arr[NR] = $0
создает массив, содержащий все записи файла.
Затем if ($0 ~ /====/) line=NR}
находит последнюю запись файла, содержащую этот шаблон. Это выражение можно записать как if (/====/) line=NR
.
И, наконец, цикл for выводит строки после последнего совпадения. Если требуются три строки, размер цикла можно изменить на 3 с помощью i<=line+3
.
if (line)
предотвратит печать первых двух строк файла, если шаблон не найден.
Но что, если шаблон найден в последней записи файла. Приведенное выше решение будет печатать пустые строки.
Следующее будет работать только в том случае, если в файле есть по крайней мере две записи после записи, содержащей этот шаблон.
awk '{ arr[NR]=$0; if ($0 ~ /====/) line=NR}END{if (line) for(i=line+1;i<=line+2;i++){ if (i < (NR -1)) print arr[i]}}' file
Следующее должно работать, если в файле есть одна или две записи после этого шаблона. Это ничего не даст, если шаблон будет найден в последней строке.
awk '{ arr[NR]=$0; if ($0 ~ /====/) line=NR}END{if (line) for(i=line+1;i<=line+2;i++){ if (i <= NR) print arr[i]}}' file
GNU sed в расширенном режиме регулярных выражений -E
Измените переменную оболочки на количество строк, которое вы хотите видеть.
n=2
sed -Ee '
/\n/q
/pattern/{
:loop
$d;N
/(.*\n){'"$n"'}/!bloop
x
}
$!d;x
/\n.*\n/D
s/.*\n//p;d
' file