시작 패턴과 끝 패턴 사이의 패턴을 기반으로 시작 패턴과 끝 패턴 사이의 텍스트 가져오기

시작 패턴과 끝 패턴 사이의 패턴을 기반으로 시작 패턴과 끝 패턴 사이의 텍스트 가져오기

나는 startStrcase 와 사이의 모든 것을 얻으려고 노력하고 있습니다. 나는 사용 방법과 그 사이에 발생하는 모든 이벤트를 이해합니다. 발생 사례를 하나만 제한하는 방법을 모르겠습니다.endStrbbbstartStrendStrsedbbb

입력 예:

fff
startStr
aaa
bbb
ccc
endStr
xxx
yyy
startStr
ddd
endStr
ddd
bbb

원하는 출력:

startStr
aaa
bbb
ccc
endStr

이것이 내가 가진 것입니다:

$ sed -n -e '/startStr/,/endStr/ p' sample.txt
startStr
aaa
bbb
ccc
endStr
startStr
ddd
endStr

답변1

첫 번째 startStr... 에 대해 endStr다음이 포함 /bbb/됩니다.

 sed -n '/startStr/ {:n; N; /endStr/ {/\n[^\n]*bbb[^\n]*\n/ {p; q}; b}; bn}'

또는

sed -n '/startStr/ {:n; N; /endStr/ {/\nbbb\n/ {p; q}; b}; bn}'

정규식이 아닌 경우 bbb정확히 필요한 문자열입니다(처음부터 까지 \n).

설명하다

주소의 경우 /startStr/:

  • 라벨 설정 :n;
  • 다음 줄 읽기 N;
  • 일치하는지 확인하십시오 /endStr/.
    • 이것이 사실이라면 /\nbbb\n/우리가 읽은 이 블록에서 발생을 확인하십시오.
      • 있는 경우 {p; q}"인쇄 및 종료"를 수행합니다.
      • 그렇지 않으면 b"이 블록을 던지고 다음 블록 검색을 시작하십시오"를 수행하십시오.
  • 블록의 끝이 아닌 경우 로 이동합니다 :n. 즉, 계속 읽습니다.

답변2

pcregrep이 직업에 대한 나의 조언은 다음과 같습니다.

pcregrep -M 'startStr(.|\n)*?bbb(.|\n)*?endStr' sample.txt

옵션을 사용하면 욕심 많은 연산자 없이 -M여러 줄 패턴을 일치시킬 수 있습니다 . *?나머지는 분명해야합니다.

답변3

이전에 일치하는 블록 이 startStr...endStr없는 블록을 포함하도록 입력 샘플을 수정합니다.bbb

$ cat ip.txt 
startStr
foo
bar
endStr
fff
baz
startStr
aaa
bbb
ccc
endStr
xxx
yyy
startStr
ddd
endStr
ddd
bbb


awk해결책

awk '/startStr/{f=1; m=0; buf = $0; next}
     /bbb/ && f{m=1}
     f{buf = buf ORS $0}
     /endStr/ && f{f=0; if(m==1)print buf}
    ' ip.txt
  • /startStr/{f=1; m=0; buf = $0; next}블록 시작을 나타내는 플래그 설정, 일치 항목 지우기, 버퍼 초기화 및 다음 줄로 이동
  • /bbb/ && f{m=1}행에 가 포함된 경우 일치를 설정합니다 bbb. 외부 f일치를 방지하는 데 사용됩니다 .bbbstartStr...endStr
  • f{buf = buf ORS $0}플래그가 설정될 때마다 입력 행을 누적합니다.
  • /endStr/ && f{f=0; if(m==1)print buf}블록 끝에서 일치하는 항목이 발견되면 버퍼를 인쇄합니다.


한 줄로:

$ awk '/startStr/{f=1; m=0; buf = $0; next} /bbb/ && f{m=1} f{buf = buf ORS $0} /endStr/ && f{f=0; if(m==1)print buf}' ip.txt 
startStr
aaa
bbb
ccc
endStr


전체 입력 파일을 흡수하여 더 간단한 perl솔루션 - 유사한 블록이 없다고 가정 startStr...startStr...endStr(예: first startStr 없음 endStr)

$ perl -0777 -ne '(@m) = /startStr.*?endStr\n/gs; print grep { /bbb/ } @m' ip.txt 
startStr
aaa
bbb
ccc
endStr

답변4

sed -n -e '/startStr/,/bbb/p;/bbb/,/endStr/p' /path/to/input

관련 정보