패턴을 찾으려면 grep을 수행해야 하고, 패턴을 찾으면 해당 패턴 이전에 다른 패턴을 찾아서 그 사이에 있는 모든 줄을 인쇄해야 합니다.
더 나은 예:
1 a
2 a
3 a
4 a
5 a
6 b
7 c
8 d
9 xyz
10 xyz
11 a
12 a
grep을 누른 xyz
다음 첫 번째 a
줄 을 grep xyz
하고 모든 줄을 인쇄합니다.
출력(첫 번째로 나타나는 출력 , 파일의 다른 출력은 a
신경 쓰지 않음 ):a
5 a
6 b
7 c
8 d
9 xyz
10 xyz
답변1
Perl의 솔루션은 다음과 같습니다.
perl -nlE '
if (/a/) { @buffer = ($_) }
elsif (/xyz/) { push @buffer,$_; say for @buffer }
else { push @buffer,$_}
' your_file
어떻게 작동하나요?
파일을 한 줄씩 읽고 다음 세 가지 작업 중 하나를 수행합니다.
- 현재 행이 패턴과 일치하면
a
현재 행이 배열에 할당됩니다@buffer
. - 현재 줄이 패턴과 일치하면
xyz
현재 줄을 버퍼에 푸시하고 버퍼의 내용을 인쇄합니다. @buffer
위의 어느 것도 해당되지 않으면 현재 행을 배열 에 추가합니다 .
따라서 새 줄이 패턴과 일치할 때마다 a
의 내용이 @buffer
삭제되고 현재 줄로만 대체됩니다. 이렇게 하면 가장 a
앞쪽에 있는 것을 찾을 수 있습니다 xyz
.
물론 내가 사용한 정규식을 귀하의 사례와 관련된 실제 정규식으로 바꿔야 합니다.
답변2
나생각하다당신은 다음과 같은 것을 할 수 있습니다
grep -zPo '.*a(?s)(?(?!a).)*?xyz' file
(귀하의 버전이 PCRE 확장을 지원할 만큼 충분히 새로운 경우 GNU grep을 사용하십시오) 또는
pcregrep -Mo '.*a(?s)(?(?!a).)*?xyz' file
xyz
출력에서 두 번째 인스턴스를 일치시키려면 ?
마지막 예를 들어 grep -zPo '.*a(?s)(?(?!a).)*xyz' file
.
아마도 더 나은 테스트는 주어진 시작 및 중지 조건 모두에 대해 다중 문자 모드를 사용하는 것입니다.
$ cat file
1 abc
2 abc
3 abc
4 abc
5 abc
6 bbc
7 cbc
8 dbc
9 xyz
10 xyz
11 abc
12 abc
그 다음에
$ grep -zPo '.*abc(?s)(?(?!abc).)*?xyz' file
5 abc
6 bbc
7 cbc
8 dbc
9 xyz
답변3
tac file | sed '/xyz/,/a/!d' | tac
(그렇지 않으면 tac
명령 에 동일한 작업을 수행 tail
하는 명령이 있을 수 있습니다 .)-r
답변4
출력에 빈 줄이 있는지 신경 쓰지 않는다면 다음을 시도해 보십시오.
$ awk '
!NF { next }
/a/ { flag = 1; last = $0; next }
last && flag { print last; print; last = 0; next}
/xyz/ { print; flag = 0; next}
flag
' file
5 a
6 b
7 c
8 d
9 xyz
10 xyz