Linux에서 sed를 사용하여 두 번째 패턴이 파일에서 더 많은 줄을 반복하는 두 패턴 사이의 문자열을 추출하는 방법

Linux에서 sed를 사용하여 두 번째 패턴이 파일에서 더 많은 줄을 반복하는 두 패턴 사이의 문자열을 추출하는 방법

예를 들어

xyz
A1
B1
C1
D1
End
End
End
X1
X2
X3
Done

xyz부터 끝 패턴까지의 모든 문자열을 추출하고 싶습니다. 그래서 출력은 다음과 같아야합니다

xyz
A1
B1
C1
D1
End
End
End

답변1

방법 1

perl -l -0777ne 'print /^(xyz.*?^End$(?:\nEnd$)*)/ms' yourfile

피복재

  • 파일은 하나의 긴 문자열로 나타나도록 읽혀지며, 그런 다음 적절한 정규식을 사용하여 분할될 수 있습니다. 이 예의 정규식은 다음과 같습니다.
    • 줄의 시작 부분에서 xyz를 찾습니다(반드시 파일일 필요는 없음).
    • 한 줄에서만 가장 가까운 끝을 찾은 다음 가능한 한 많은 연속 줄을 찾습니다.

방법 2

perl -lne '
   next unless /xyz/ ... eof;
   last if !/End/ and $flag;
   $flag ||= 1 if /End/;
   print;
' yourfile

피복재

  • 여기서는 라인별로 Perl을 작동하고 작은 상태 머신을 설정합니다.
    • 파일의 범위가 아닌 부분을 거부합니다.
    • 올바른 범위를 입력하면 /End/ 줄에 도달할 때까지 모든 줄을 인쇄합니다. 그때 우리는 표지판을 세웠습니다.
    • 그런 다음 /End/가 아닌 첫 번째 줄을 보면 폭발합니다.

방법 3

sed -e '
   /xyz/!d
   :a
      $q;N
   /\nEnd$/!ba
   :b
      n
   /End/bb
   d
' yourfile

이 방법에서는 /xyz/에서 /End/까지 줄을 누적하는 첫 번째 do-while 루프(:a)를 작동합니다.

두 번째 do-while 루프(:b)는 다음 줄이 /End/가 될 때까지 줄을 인쇄합니다.

방법 4

sed -e '
   /xyz/,/End/!d
   H;/xyz/h;/End/!d
   :a
      $q;N
      /\(.*\)\n\1$/!{g;q;}
      s/.*\n//;H
   ba
' yourfile

이 접근 방식을 사용하여 먼저 올바른 범위를 선택한 다음 해당 범위 데이터를 저장 공간에 저장합니다. do-while 루프(:a)는 예약된 공간에 점진적으로 추가되도록 설정되어 있으며 다음 줄은 /End/입니다.

결과

xyz
A1
B1
C1
D1
End
End
End

답변2

pcregrep직업은 다음과 같은 일을 잘합니다:

pcregrep -M 'xyz(.|\n)*End' file

욕심이 많아 끝까지 다 먹지 않으니 주의하세요, 기타 포함에스.

답변3

Perl이 도움을 줍니다. xyz첫 번째 줄과 마지막 줄 사이의 모든 줄을 인쇄합니다 End.

 perl -ne '
     $inside = 1        if /^xyz$/;
     $seen_end = 1      if $inside && /^End$/;
     push @buff, $_     if $inside;
     print splice @buff if /^End$/ && @buff;
' input-file

첫 번째 발생부터 시작하여 xyz모든 행을 버퍼로 푸시하기 시작합니다. 일단 End발생하면 버퍼를 출력하고 지웁니다(참조접합End), 그러나 나중에 다른 행이 나타날 경우를 대비하여 행을 버퍼에 계속 푸시합니다 .

답변4

해결책:

awk '/xyz/,/End/{ print $0; n=NR }($0=="End" && n && NR>n && NR-n++ == 1)' file

산출:

xyz
A1
B1
C1
D1
End
End
End

  • /xyz/,/End/- 기록 범위, 에서 xyz까지End

  • n=NR- 캡처 레코드 번호(범위 일치 시 - 최종적으로 범위를 포함하게 될 마지막 레코드의 번호)

관련 정보