현재 해결하는 데 도움이 필요한 문제가 발생했습니다. 올바른 방향을 가리키는 것조차 도움이 됩니다.
줄이 많은 파일이 있는데 특정 패턴을 따르는 특정 줄 "그룹"만 추출하고 싶습니다. (한 줄은 로 시작해야 하고 A
, 다음 줄은 로 시작해야 하며 B
, 다음 줄은 로 시작해야 합니다 C
)
예: 모드: , A
, B
순서 C
로 시작합니다 .
입력하다:
A1
B1
C1
D1
A2
B2
D2
A3
D3
A4
B4
C4
A5
B5
D5
산출:
A1
B1
C1
A4
B4
C4
답변1
또 다른 해결책 awk
:
awk 'p2~/^A/ && p1~/^B/ && /^C/{print p2 RS p1 RS $0} {p2=p1; p1=$0}'
perl
전체 입력을 단일 문자열로 읽습니다 .
perl -0777 -ne 'print /^A.*\nB.*\nC.*\n/mg'
그리고립그렙편리한 다중 라인 매칭 옵션을 지원합니다.-U
rg -oUN '^A.*\nB.*\nC.*'
여기서 -o
옵션은 일치하는 부분만 가져오는 것이고 -N
옵션은 출력에서 줄 번호를 방지하는 것입니다.
답변2
Sed 솔루션도 원한다면 보기 흉하지만 작동할 것입니다.
sed -n '
/^A/{
N
/\nB/!D
N
/\nC/!{
s/\n//
D
}
p
}
' file
-n
p
sed에게 명령에 도달하지 않는 한 아무것도 인쇄하지 말라고 지시합니다 .
첫 번째 부분을 이해하면 나머지 부분도 이해할 수 있습니다.
/^A/
패턴 공간이 A로 시작하면,N
패턴 공간에 다음 줄을 추가합니다./\nB/!D
패턴 공간에 B 뒤에 개행 문자가 없으면 첫 번째 개행 문자 앞의 모든 내용이 삭제되고 입력을 읽지 않고 결과 패턴 공간으로 다시 시작됩니다.
짧막 한 농담:sed -n '/^A/{N;/\nB/!D;N;/\nC/!{s/\n//;D};p}' file
답변3
다음 awk
절차가 작동합니다.
awk 's==2{if (/^C/) {s=0; p=p ORS $0; print p} else {s=0}}\
s==1{if (/^B/) {s=2; p=p ORS $0} else {s=0}}\
s==0{if (/^A/) {s=1; p=$0}}' input.txt
이는 내부 "상태" 플래그를 유지하여 s
시퀀스의 어떤 지점(0: 시작을 찾을 수 없음, 1: A
찾을 수 없음, 2: 시퀀스 A
에서 발견 B
)을 확인하고 텍스트를 버퍼에 축적합니다 p
.
A
과 가 발견B
되고 현재 줄이 로 시작하면C
현재 줄을 버퍼에 추가하고 인쇄합니다. 상태 재설정0
- 발견 되고
A
현재 줄이 로 시작하면B
현재 줄을 버퍼에 추가하고 상태를2
(=A
및B
발견) 으로 설정합니다. - 시작 부분을 아직 찾지 못했고 현재 줄이 로 시작하는 경우
A
이를 버퍼에 추가하고 상태를 로 설정합니다1
.
답변4
이전 상태가 A->B->C로 이어지는 경우에만 sed에서 상태 머신을 설정하여 다음 상태로 진행할 수 있습니다.
그렇지 않으면 머리를 자르고 다시 시작하십시오.
$ sed -e '$d;/\n/d
/^A/N;/\nB/!D
$!N;/\nC/!D
' file
A1
B1
C1
A4
B4
C4
다음 grep 코드는 PCRE 옵션으로 gnu grep을 컴파일한 경우 또 다른 방법입니다.
$ grep -zoP '(?m)^A.*\nB.*\nC.*\n' file | tr -d '\0'