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

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

좋은 아침입니다. 질문과 매우 유사합니다.마지막 패턴 발생에서 다른 패턴으로 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변수가 인쇄 되고 다시 0으로 a설정됩니다 .f

답변2

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

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

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

이는 다음을 의미합니다.

"condition2" 패턴과 일치하는 각 줄(전역)에 대해 g"condition1"의 이전 인스턴스를 뒤로 검색하고 해당 줄부터 현재 줄(예: "condition2"가 있는 줄)까지의 모든 줄을 p인쇄합니다 ..

제공된 입력에 대한 출력은 설명과 정확히 같습니다.

답변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),
  • grep조건 2( ) 에 나타나지 않는 단락을 필터링하고 ,
  • 그런 다음 관심 있는 각 단락에서 조건부 2줄( ) map뒤의 모든 줄을 제거합니다.

관련 정보