Как напечатать строки между паттерном1 и вторым совпадением паттерна2?

$ 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

$
4
28.06.2016, 14:50
4 ответа

Просто используйте флаги:

$ awk '/PATTERN1/{flag=2;next} flag; /PATTERN2/{flag--}' file
a
b
c
PATTERN2
d
e
f
PATTERN2

То есть: когда вы найдете ШАБЛОН1 , установите флаг в положительное значение; в частности, 2. Затем, когда вы найдете ШАБЛОН2 , уменьшите этот флаг на один. Таким образом, он иссякнет после второго матча. Между ними используйте флаг как значение, которое запускает {print $ 0} , когда оно имеет истинное значение (2 или 1).

5
27.01.2020, 20:45

Если мы сказали, что относительно sed слишком легко собрать необходимые строки, то выведите

sed -n '
    /PATTERN1/{
        :1
        $!N
        /\(PATTERN2\).*\1/!b1
        p
    }
' file
2
27.01.2020, 20:45

Правильный инструмент для этого задания - pcregrep :

pcregrep -M 'PATTERN1(.|\n)*PATTERN2' file

, где опция -M позволяет шаблону соответствовать более чем одной строке, а (. | \ N) * соответствует любому символу или новой строке ноль или более раз.

Обратите внимание, что мы воспользовались жадностью grep. Если вы хотите напечатать образец формы 1 до первого появления образца 2, то вместо * следует использовать нежадный *? .

В качестве обобщения, чтобы напечатать до n -го появления ШАБЛОН2:

pcregrep -M 'PATTERN1((.|\n)*?PATTERN2){n}' file

Замените n на фактическое число, которое вам нужно.

5
27.01.2020, 20:45

Вот один из способов сделать это с помощью 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 .

6
27.01.2020, 20:45

Теги

Похожие вопросы