awk / pattern / {print“text”} / patern / {print“”}을 사용할 때 ELSE 패턴이 있습니까?


22

다음과 같은 텍스트 파일이 있다고 가정 해 봅시다.

R1 12 324 3453 36 457 4 7 8
R2 34 2342 2525 25 25 26 26 2 2
R3 23 2342 32 52 54 543 643 63
R4 25 234 2342 4 234242

awk이 라인을 다르게 처리하는 데 사용 하고 싶습니다.

awk '/R1/ { print "=>" $0} /R2/ { print "*" $0} '

그리고 나머지 줄을 그대로 인쇄하고 싶습니다 (이미 처리 한 줄을 복제하지 않고), 기본적으로 줄 /ELSE/ { print $0}끝에 필요합니다 awk.

그런 것이 있습니까?

답변:


27

간단한 접근 방식 awk

awk '/R1/ {print "=>" $0;next} /R2/{print "*" $0;next} 1' text.file

[jaypal:~/Temp] cat text.file 
R1 12 324 3453 36 457 4 7 8
R2 34 2342 2525 25 25 26 26 2 2
R3 23 2342 32 52 54 543 643 63
R4 25 234 2342 4 234242

[jaypal:~/Temp] awk '/R1/ { print "=>" $0;next} /R2/{print "*" $0;next}1' text.file
=>R1 12 324 3453 36 457 4 7 8
*R2 34 2342 2525 25 25 26 26 2 2
R3 23 2342 32 52 54 543 643 63
R4 25 234 2342 4 234242
[jaypal:~/Temp] 

패턴 {Action} 문 :

  • /R1/ { print "=>" $0;next}: 이것은 /R1/인쇄 작업 =>이있는 행이 수행됨을 의미합니다. nextawk 문장의 나머지 부분은 무시되고 다음 줄을 볼 것임을 의미합니다.

  • /R2/{print "*" $0;next}: 이것은 pattern /R2/인쇄 작업과 일치하는 행이 *수행됨을 의미합니다. 때 awk시작 처리, 최초의 pattern {action}(가)로 문이 무시됩니다 pattern /R1/가진 라인을위한 진정한되지 않습니다 /R2/. 따라서 두 번째 pattern {action}진술은 라인에서 이루어집니다. next다시 한 번 더 처리를 원하지 않으며 awk다음 줄로 넘어갑니다.

  • 1모든 줄을 인쇄합니다. 조건없이 no가 제공 {action}되면 awk는 기본적으로를 사용 {print}합니다. 여기서 조건은 1참으로 해석되므로 항상 성공합니다. 우리가이 지점에 도착하면, 제 1 및 제 2 때문입니다 pattern {action}문이 무시되거나 (포함하지 않는 라인에 의해-전달 된 /R1//R2/기본 인쇄 작업이 남아있는 라인에 대해 수행 할 수 있도록,).


게시 된 모든 솔루션 중에서 가장 빠른 속도로 실행되는 것 같습니다.
Chris Down

1
구문 설탕 이 올바른 용어 인지 잘 모르겠습니다. 구문 일뿐입니다.
Daniel Hershcovich

7

awk조건부와 관련하여 일반적인 용의자를 구현합니다. 일치하고 싶은 일 printf대신에 사용하는 것이 좋습니다 print.

awk '{ if (/^R1/) { printf("=> %s\n", $0) } else if (/^R2/) { printf("* %s\n", $0) } else { print $0 } }'

당신은 정말로 if-then-else이것을 필요 로 하지 않습니다 .
jaypal 싱

1
이것은 완벽하게 작동하지만 관용적이지는 않습니다. 신중하게 사용 next하는 것은 awk 프로그래밍에서 중요한 도구입니다.
dmckee

2
printf여기서 사용하는 요점을 이해하지 못합니다 . 연결보다 더 멋진 형식을 지정하지 않는 한 유일한 이점은 줄 바꿈을 추가하지 않는다는 것입니다.
Gilles 'SO- 악한 중지

1
그것은 반 직관적이고 놀라운 결과입니다. Unadorned print는 출력 만하 는 $0반면 printf형식 문자열을 구문 분석해야합니다.
jw013

5

Chris Down은 블록에 명시적인 'if'문을 사용하여 정규 표현식에 대한 else를 얻는 방법을 이미 보여주었습니다. 그의 해결책이 더 나을 수도 있지만 다른 방법으로도 동일한 효과를 얻을 수 있습니다.

하나는 다른 것과 일치하지 않는 텍스트와 만 일치하는 세 번째 정규 표현식을 작성하는 것입니다.이 경우 다음과 같이 보일 것입니다.

awk '/^R1/ { print "=>" $0}
     /^R2/ { print "*" $0}
     /^[^R]/ || /^R[^12]/ { print $0 } '

이것은 고정 된 정규 표현식을 사용합니다-정규 표현식의 시작 부분에있는 ^는 줄의 시작 부분에서만 일치합니다-원래 패턴은이 작업을 수행하지 않았습니다. 다음 줄까지 건너 뜁니다. 세 번째 ( "else")는 'R'([^ R])이 아닌 일부 문자로 시작하거나 'R'로 시작하고 그 뒤에 '1'또는 '이 아닌 문자가 오는 행과 일치합니다. 2 '(R [^ 12]). ^의 두 가지 다른 의미는 다소 혼란 스럽지만 그 실수는 오래 전에 만들어졌으며 곧 바뀌지 않을 것입니다.

보완 정규 표현식을 사용하려면 실제로 고정해야합니다. 그렇지 않으면 [^ R]이 뒤에 오는 1과 일치합니다. 매우 간단한 정규식의 경우이 방법이 유용 할 수 있지만 정규식이 복잡해지면이 방법을 관리 할 수 ​​없게됩니다. 대신 다음과 같이 각 줄에 상태 변수를 사용할 수 있습니다.

awk '{ handled = 0 }
     /^R1/ { print "=>" $0; handled = 1}
     /^R2/ { print "*" $0; handled = 1}
     { if (!handled) print $0 } '

이렇게하면 각 줄 바꿈마다 처리 된 값이 0으로 설정되고 두 정규 표현식 중 하나와 일치하면 1로 설정되고 마지막으로 여전히 0 인 경우 $ 0 인쇄를 실행합니다.


큰 파일의 경우 두 조건 모두 조건을 사용하는 것보다 효율적이지 않습니다 ( 여기 참조 ). rfile질문자 데이터 세트의 10000 줄만 반복됩니다.
Chris Down

4
if (!handled)왝! next다른 조치를 고려하지 않을 때 사용하십시오 .
dmckee

일에 대한 if (!handled). 일반적이고 유연하며 재사용 가능한 솔루션이 좋습니다. 이 질문이있는 다음 사람이 인쇄 후에 더 많은 처리를 원한다면 어떻게해야합니까? 대답 next은 그것을 지원하지 않습니다.
Scott
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.