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