특정 패턴의 마지막 발생부터 다른 패턴의 첫 번째 발생까지 인쇄 범위

특정 패턴의 마지막 발생부터 다른 패턴의 첫 번째 발생까지 인쇄 범위

좋은 아침입니다. 질문과 매우 유사합니다.패턴의 마지막 발생에서 다른 패턴으로 Grep(몇 달 전), 좀 더 자세한 내용을 추가합니다.

여러 개의 중복 패턴과 내가 찾고 있는 패턴이 이어지는 파일에 대한 UNIX 스크립트를 작성하려고 합니다. 그러나 'tac' 또는 'tail -r'(UNIX 에뮬레이터, MKS Toolkit 사용)이 없으며 Pattern2 이전에 Pattern1의 마지막 항목을 반환하고 그 뒤에 Pattern1과 Pattern2 사이의 데이터, Pattern2를 반환하려고 합니다. 또한. 이 경우 패턴은 '조건 1'과 '조건 2'입니다.

출력.출력:

...
Condition 1: A
data1
Condition 1: B
data2
Condition 2: C
data3
Condition 1: D
data4
Condition 1: E
data5
Condition 2: F
...

반환할 awk(또는 sed이지만 awk가 올바른 도구라고 생각함) 스크립트를 작성하고 싶습니다.

Condition 1: B
data2
Condition 2: C
Condition 1: E
data5
Condition 2: F

나는 이것이 아래 줄의 어떤 형태라고 생각하지만 구문을 올바르게 얻을 수 없습니다.

awk '/Condition 1/ {acc = $0;} /,/Condition 2/ {print ?}' output.out

'/,/' 작업에서 끊김 현상이 발생하는 것 같습니다. 누구든지 조언이 있는지 궁금합니다. 정말 감사하겠습니다. 이 질문과 관련된 도움과 시간을 보내주셔서 감사합니다.

답변1

노력하다:

$ awk 'f{a=a"\n"$0} /Condition 1/{a=$0; f=1} f && /Condition 2/{print a; f=0}' output.out 
Condition 1: B
data2
Condition 2: C
Condition 1: E
data5
Condition 2: F

작동 원리

  • f{a=a"\n"$0}

    변수가 ftrue(0이 아님)이면 현재 줄을 변수 끝에 추가합니다 a.

  • /Condition 1/{a=$0; f=1}

    현재 줄에 가 포함되어 있으면 현재 줄로 Condition 1설정 하고 변수를 1로 설정합니다.sf

  • f && /Condition 2/{print a; f=0}

    ftrue이고 현재 줄에 가 포함되어 Condition 2있으면 변수를 인쇄 a하고 f다시 0으로 설정합니다.

답변2

텍스트 처리에서 역방향 주소 지정을 원할 경우 다음을 사용하십시오.ex

그것은POSIX 지정, 그리고 이는 vi(및 vi의 바로 전임자)의 스크립트 가능한 형식으로 매우 유연합니다.

printf '%s\n' 'g/Condition 2/?Condition 1?,.p' | ex output.out

이는 다음을 의미합니다.

g"조건 2" 패턴과 일치하는 모든 줄(전체적으로)에 대해 "조건 1"의 바로 이전 인스턴스를 역방향으로 검색하고 p해당 줄부터 현재 줄( .)("조건 2"가 있는 줄) 까지 모든 줄을 린트합니다. 그것).

제공된 입력의 출력은 설명과 똑같습니다.

답변3

sed 'H;/PATTERN_1/h;/PATTERN_2/!d;x' infile

그러나 이는 일치하는 줄 PATTERN_2앞에 일치하는 줄이 하나 이상 있다고 가정합니다 PATTERN_1. 보다 일반적인 경우에는 PATTERN_1인쇄하기 전에 패턴 공간에 존재하는지 테스트하기 위해 또 다른 조건을 추가합니다.

sed 'H;/PATTERN_1/h;/PATTERN_2/!d;x;/PATTERN_1/!d' infile

답변4

다음은 Perl의 사악한 부분입니다.

perl -0777 -ne '
    my $c1 = qr/Condition 1/;
    my $c2 = qr/Condition 2/;
    print for map {s/$c2.*?\n\K.*//s; $_}
              grep {/$c2/}
              split /(?=$c1)/ms;
' output.out

그것:

  • 전체 파일을 읽습니다( -0777-n옵션 사용).
  • 조건 1이 나타나는 곳에서 분할합니다( split).
  • 조건 2가 나타나지 않는 단락을 필터링합니다( grep).
  • 그런 다음 각 흥미로운 단락에서 조건 2 행( map) 다음에 오는 모든 행을 제거합니다.

관련 정보