awk를 사용하여 패턴의 일부 또는 전부를 일치시킵니다.

awk를 사용하여 패턴의 일부 또는 전부를 일치시킵니다.

awk의 다중 패턴 일치에 대해 이해할 수 없는 작은 문제가 있습니다. 다음과 같은 awk 줄이 있습니다.

awk '/pat1/{v1=$4; next} /pat2/{v2=$5; next} /pat3/{v3=$6;next} /pat4/{v4=$5; print v1,"    ",v2,"    ",v3"    ",v4}' myfile.out

이것은 모두 일치하기 때문에 내가 원하는 결과(각 일치 항목에 대해 한 줄에 수학 결과를 인쇄)를 제공합니다. 패턴 중 하나가 존재하지 않으면 아무것도 일치하지 않습니다.

따라서 모두 일치하면 예상한 결과를 얻습니다.

pat1    pat2    pat3    pat4
pat1    pat2    pat3    pat4
pat1    pat2    pat3    pat4
pat1    pat2    pat3    pat4
.
.
.

각 행마다 patX다른 값이 있습니다!

이 공간을 비워 두지 않은 것처럼 보일 경우 awk에게 이러한 패턴을 찾도록 지시할 수 있는 방법이 있습니까?

예를 들어, 첫 번째 인스턴스에서 업데이트 중인 문서에 pat3아직 존재하지 않는 경우 다음을 얻어야 합니다.pat4

pat1    pat2    
pat1    pat2   pat3    ------> (here let's assume that pat3 has made an appearange)
pat1    pat2   pat3    pat4 ------> (here pat4 started to appear too)
pat1    pat2   pat3    pat4
pat1    pat2   pat3    pat4
.
.
.

awk로 할 수 있나요?

편집: 다음은 제가 직면하고 있는 두 가지 예시 시나리오입니다. 내 파일은 비어 있는 상태로 시작한 다음 일부 패턴을 필터링해야 하는 데이터로 채워집니다. 모든 패턴이 처음부터 나타나는 것은 아닙니다. 따라서 파일은 다음과 같이 시작됩니다.

some text here pat1
some more text here

some more text here pat2

some more text here and pat3


위의 awk 명령을 사용하면 pat4아직 존재하지 않기 때문에 빈 결과가 제공됩니다! 시간이 지나면 결국 나타나게 됩니다.

some text here pat1
some more text here

some more text here pat2

some more text here and pat3

some more text here pat4

some text here pat1
some more text here

some more text here pat2

some more text here and pat3

some more text here pat4

some text here pat1
some more text here

some more text here pat2

some more text here and pat3

some more text here pat4

이 명령의 결과는 awk예상한 대로 나타납니다.

pat1      pat2      pat3     pat4
pat1      pat2      pat3     pat4
pat1      pat2      pat3     pat4

그러나 처음에 얻고 싶었던 결과는 다음과 같습니다.

pat1    pat2    pat3   

이제 더 명확해지기를 바랍니다. (위의 awk 명령을 더 간단하게 만들기 위해 다시 작성하고 테스트했습니다.)

답변1

다음과 같은 것이 필요한 것 같습니다.

$ cat tst.awk
BEGIN { OFS="     " }

{ sub(/\r$/,"") }

( ($NF ~ /pat1/) && (state == 0) ) ||
( ($NF ~ /pat2/) && (state == 1) ) ||
( ($NF ~ /pat3/) && (state == 2) ) ||
( ($NF ~ /pat4/) && (state == 3) ) {
    v[++state] = $NF
}

state == 4 {
    print v[1], v[2], v[3], v[4]
    state = 0
}

$ awk -f tst.awk file
pat1     pat2     pat3     pat4
pat1     pat2     pat3     pat4
pat1     pat2     pat3     pat4

답변2

아마도 END 절을 사용하여 결과를 인쇄할 수도 있습니다.

    awk '/pat1/{v1=$4; next} /pat2/{v2=$5; next} /pat3/{v3=$6; next} /pat4/{v4=$5;} END{ print v1,"    ",v2,"    ",v3"    ",v4 }' myfile.out

답변3

내 질문에 @EdMorton의 답변을 적용하려고 노력하는 동안 이전에 누군가에게서 필요한 정보를 찾았습니다.철사그는 답변을 제공하고 문제를 완전히 해결했습니다. 이것이 내 해결책입니다.

awk '/pat1/{v1=$4; next}{v1="xxx"} /pat2/{v2=$5; next}{v2="xxx"} /pat3/{v3=$6;next}{v3="xxx"} /pat4/{v4=$5}{v4="xxx"} {print v1,"    ",v2,"    ",v3"    ",v4}' myfile.out

이제 패턴 중 하나가 아직 존재하지 않으면 xxx그 자리에서 패턴을 찾아보겠습니다. xxx단일 공백 ​​문자나 다른 값으로 바꿀 수 있습니다 .

모든 조언과 도움에 감사드립니다!

추신: 때때로 문제를 설명하기 위해 예제 입력을 제공하는 것이 쉽지 않다는 것을 알았습니다. 이로 인해 실망하셨다면 죄송합니다!

답변4

Raku(이전 Perl_6) 사용

raku -e 'my @a; my @pat = <<pat1 pat2 pat3 pat4>>; for lines() { for @pat -> $i { @a.push( m[$i] // " __ " ) };}; .put unless $_ eq " __   __   __   __ " for @a.rotor(4);'

까다로운 질문으로 인해 Raku에서 답변했습니다. 한 줄에 필수 항목이 두 개 이상 포함되어 있으면 어떻게 되나요 pattern? 아니면 pattern오작동이 있나요? 아래 코드는 이러한 경우를 처리합니다(또한 패턴을 찾을 수 없는 줄을 제거합니다).

샘플 입력의 마지막 몇 줄과 샘플 출력의 마지막 몇 줄에서 추출된 패턴을 살펴보세요. (아래 예에서는 빈 줄을 제거했습니다.)

입력 예:

some text here pat1
some more text here
some more text here pat2
some more text here and pat3
some more text here
some text here pat1
some more text here
some more text here pat2
some more text here and pat3
some more text here pat4
some text here pat1
some more text here
some more text here pat2
some more text here and pat3
some more text here pat4
some more text here pat1 pat2
some more text here pat1 pat2 pat3 pat4

예제 출력:

pat1  __   __   __ 
 __  pat2  __   __ 
 __   __  pat3  __ 
pat1  __   __   __ 
 __  pat2  __   __ 
 __   __  pat3  __ 
 __   __   __  pat4
pat1  __   __   __ 
 __  pat2  __   __ 
 __   __  pat3  __ 
 __   __   __  pat4
pat1 pat2  __   __ 
pat1 pat2 pat3 pat4

참고: 일반적인 상황은 다음과 같습니다.아니요위의 코드는 행의 여러 복사본에서 단일 패턴이 발견되는 경우를 처리합니다. 위의 코드에는 발생 횟수를 계산하는 메커니즘이 없으며 패턴이 "표시되는지"만 알려줍니다. 아래 예:

echo "text here pat2 pat2 pat2 pat4" | raku -e 'my @a; my @pat = <<pat1 pat2 pat3 pat4>>; for lines() { for @pat -> $i { @a.push( m[$i] // " __ " ) };}; .put unless $_ eq " __   __   __   __ " for @a.rotor(4);'

반복 패턴 출력:

__  pat2  __  pat4

http://raku.org

관련 정보