$ cat /tmp/tmp.tmp
release-5.0.0.rc1
release-5.0.0.rc2
release-5.0.0
release-5.0.1
release-5.0.10
release-5.0.11
release-5.0.13
release-5.0.14
release-5.0.15
release-5.0.16
release-5.0.17
release-5.0.18
release-5.0.19
release-5.0.2
release-5.0.20
release-5.0.21
release-5.0.22
release-5.0.23
release-5.0.24
release-5.0.25
release-5.0.26
release-5.0.27
release-5.0.28
release-5.0.29
release-5.0.3
$ cat /tmp/tmp.tmp | awk -F\- '{ print $2,$1 }' | sort -n | awk '{ print $2 "-" $1 }'
release-5.0.0
release-5.0.0.rc1
release-5.0.0.rc2
release-5.0.1
release-5.0.10
release-5.0.11
release-5.0.13
release-5.0.14
release-5.0.15
release-5.0.16
release-5.0.17
release-5.0.18
release-5.0.19
release-5.0.2
release-5.0.20
release-5.0.21
release-5.0.22
release-5.0.23
release-5.0.24
release-5.0.25
release-5.0.26
release-5.0.27
release-5.0.28
release-5.0.29
release-5.0.3
$
Просто используйте флаги:
$ awk '/PATTERN1/{flag=2;next} flag; /PATTERN2/{flag--}' file
a
b
c
PATTERN2
d
e
f
PATTERN2
То есть: когда вы найдете ШАБЛОН1
, установите флаг в положительное значение; в частности, 2. Затем, когда вы найдете ШАБЛОН2
, уменьшите этот флаг на один. Таким образом, он иссякнет после второго матча. Между ними используйте флаг
как значение, которое запускает {print $ 0}
, когда оно имеет истинное значение (2 или 1).
Если мы сказали, что относительно sed
слишком легко собрать необходимые строки, то выведите
sed -n '
/PATTERN1/{
:1
$!N
/\(PATTERN2\).*\1/!b1
p
}
' file
Правильный инструмент для этого задания - pcregrep
:
pcregrep -M 'PATTERN1(.|\n)*PATTERN2' file
, где опция -M
позволяет шаблону соответствовать более чем одной строке, а (. | \ N) *
соответствует любому символу или новой строке ноль или более раз.
Обратите внимание, что мы воспользовались жадностью grep. Если вы хотите напечатать образец формы 1 до первого появления образца 2, то вместо *
следует использовать нежадный *?
.
В качестве обобщения, чтобы напечатать до n
-го появления ШАБЛОН2:
pcregrep -M 'PATTERN1((.|\n)*?PATTERN2){n}' file
Замените n
на фактическое число, которое вам нужно.
Вот один из способов сделать это с помощью sed
:
sed '/PATTERN1/,$!d;/PATTERN2/{x;//{x;q;};g;}' infile
Это просто удаляет все строки (если есть) до первого появления PATTERN1
, а затем в каждой строке, которая соответствует ШАБЛОН2
и x
изменяет буферы. Если новое пространство шаблонов также совпадает, это означает, что это второе вхождение, поэтому e x
возвращается обратно и q
uits (после автоматической печати). Если он не совпадает, это означает, что это первое вхождение, поэтому он копирует содержимое удерживаемого пространства в пространство шаблонов через g
(так что теперь есть строка, соответствующая PATTERN2
в буфере удержания) и продолжается ...
и другим способом с awk
:
awk '/PATTERN1/{t=1}; t==1{print; if (/PATTERN2/){c++}}; c==2{exit}' infile
Он начинает печатать и подсчитывать строки, соответствующие PATTERN2
, только когда встречает совпадение строк ШАБЛОН1
и завершается, когда c
встречный достигает 2
.