awk의 슬러 프 모드?


16

같은 도구 sed를 사용 awk하거나 perl -n한 번에 한 레코드 씩 입력을 처리합니다 . 기본적으로 레코드 입니다.

awkwith RS, sedwith -z또는 perlwith 와 같은 일부 -0ooo는 다른 레코드 구분 기호를 선택하여 레코드 유형을 변경할 수 있습니다.

perl -n전체 입력을 하나의 (여러 파일을 통과 한 각 개별 파일) 할 수 있습니다 기록-0777(또는 옵션 -0777은 정규 하나되고, 0377보다 8 진수의 큰 다음을). 그것이 그들이 slurp mode 라고 부르는 것 입니다.

비슷한 일을 함께 할 수 awkRS또는 다른 어떤 메커니즘? awk파일의 과 반대로 각 파일 내용을 전체적으로 처리하는 위치는 어디 입니까?

답변:


15

단일 문자 (전통적인 구현 과 같은 ) 또는 정규식 (같은 또는 수행)으로 awk취급 되는지에 따라 다른 접근 방식을 취할 수 있습니다 . 빈 파일도 건너 뛰는 경향이 있는 것으로 간주하기 까다 롭습니다 .RSawkgawkmawkawk

gawk, mawk또는 다른 awk구현 예는 어디 RSregexp와 수있다.

이러한 구현에서 ( mawk데비안과 같은 일부 OS 는 @ThomasDickey가 관리하는 최신 버전 대신 매우 오래된 버전을 제공 한다는 점에 유의하십시오 ) RS단일 문자 가 포함되어 있으면 레코드 구분 기호가 해당 문자이거나 비어 awk있을 때 단락 모드로 들어갑니다. 그렇지 않으면 정규식으로 RS취급합니다 RS.

해결책은 일치시킬 수없는 정규식을 사용하는 것입니다. 일부는 x^또는 $x( x시작 전 또는 끝 후)을 생각합니다. 그러나 일부 (특히와 함께 gawk)는 다른 것보다 비쌉니다. 지금까지는 ^$이것이 가장 효율적인 것으로 나타났습니다 . 빈 입력에서만 일치 할 수 있지만 일치하는 것은 없습니다.

그래서 우리는 할 수 있습니다 :

awk -v RS='^$' '{printf "%s: <%s>\n", FILENAME, $0}' file1 file2...

그러나 한 가지주의 사항은 빈 파일을 건너 뜁니다 (와 반대로 perl -0777 -n). 대신 awk코드를 ENDFILE문장 에 넣어서 GNU로 해결할 수 있습니다 . 그러나 $0빈 파일을 처리 한 후에는 재설정되지 않으므로 BEGINFILE 문에서 재설정해야 합니다.

gawk -v RS='^$' '
   BEGINFILE{$0 = ""}
   ENDFILE{printf "%s: <%s>\n", FILENAME, $0}' file1 file2...

전통적인 awk구현, POSIXawk

그에서, RS단지 하나의 문자, 그들은 가지고 있지 않은 BEGINFILE/ ENDFILE, 그들은이없는 RT변수, 그들은 또한 일반적으로 NUL 문자를 처리 할 수 없습니다.

RS='\0'어쨌든 NUL 바이트를 포함하는 입력을 처리 할 수 ​​없으므로 사용 하면 작동 할 수 있다고 생각합니다 . 그러나 RS='\0'전통적인 구현 RS=에서는 단락 모드 인 으로 취급 됩니다.

한 가지 해결책은 입력에서 찾을 수없는 문자를 사용하는 것 \1입니다. 멀티 바이트 문자 로케일에서는 $'\U10FFFE'UTF-8 로케일에서 와 같이 할당되지 않은 문자 또는 문자가 아닌 문자를 형성하므로 발생하지 않을 바이트 순서로 만들 수도 있습니다 . 정말 바보는 아니며 빈 파일에도 문제가 있습니다.

또 다른 해결책은 전체 입력을 변수에 저장하고 마지막에 END 문에서 처리하는 것입니다. 즉, 한 번에 하나의 파일 만 처리 할 수 ​​있습니다.

awk '{content = content $0 RS}
     END{$0 = content
       printf "%s: <%s>\n", FILENAME, $0
     }' file

이는의 것과 같습니다 sed.

sed '
  :1
  $!{
   N;b1
  }
  ...' file1

이 방법의 또 다른 문제는 파일이 줄 바꿈 문자로 끝나지 않고 비어 있지 않은 경우 여전히 임의로 $0끝에 추가됩니다 (와 함께 대신에 를 gawk사용하여 RT해결할 수 있음) RS위의 코드). 한 가지 장점은 NR/에 파일의 줄 수를 기록한다는 것 FNR입니다.


마지막 부분에 관해서는 ( "파일이 개행 문자로 끝나지 않고 비어 있지 않은 경우, 끝 부분에서 $ 0에 임의로 추가됩니다") : 텍스트 파일의 경우 끝이 있어야합니다 개행. vi는 예를 들어 하나를 추가하므로 파일을 저장할 때 파일을 수정합니다. 종료 줄 바꿈이 없으면 일부 명령은 마지막 "줄"(예 : wc)을 삭제하지만 다른 명령은 여전히 ​​마지막 줄 ... ymmv를 '표시'합니다. 따라서 텍스트 파일을 처리 해야하는 경우 솔루션이 유효합니다. awk는 텍스트 처리에는 좋지만 바이너리에는 좋지 않기 때문에 ^^)
Olivier Dulac

1
모든 것을 욕하는 것은 몇 가지 한계에 부딪 칠 수 있습니다 ... 전통적인 awk는 한 줄에 99 필드의 한계를 가지고 있었을 것입니다 ... 따라서 그 한계를 피하기 위해 다른 FS를 사용해야 할 수도 있습니다. 또한 한 줄의 총 길이 (또는 한 줄에 모두 넣을 경우 전체 길이)에 제한이 있습니까?
Olivier Dulac

마지막으로 : (어리석은 ...) 핵은 전체 파일을 먼저 구문 분석하고 거기에없는 문자를 찾은 다음 tr '\n' 'thatchar' 파일을 awk로 보내기 전에 tr 'thatchar' \n'출력하고 출력 하는 것일 수 있습니다 . (위에서 언급했듯이 입력 파일에 종료 줄 바꿈이 있는지 확인하기 위해 줄 바꿈을 추가해야 할 수도 있습니다. { tr '\n' 'missingchar' < thefile ; printf "\n" ;} | awk ..... | { tr 'missingchar' '\n' }(그러나 끝에 '\ n'을 추가하면 제거해야 할 수도 있습니다. tr이 개행을 종료하지 않고 파일을 받아들이면 마지막 tr 앞에 sed를 추가 하는가 ...)
Olivier Dulac

@OlivierDulac, NF 또는 모든 필드에 액세스하는 경우에만 필드 수 제한이 적용됩니다. awk우리가하지 않으면 분할을하지 않습니다. /bin/awk1970 년대 awk를 기반으로 한 Solaris 9 조차도 그 한계가 없었기 때문에 우리가 할 수있는 것을 찾을 수 있는지 확실하지 않습니다 (아직 SVR4의 oawk는 99와 nawk 199로 제한되어 있으므로 가능합니다) 아마도 그 한계의 해제가 Sun에 의해 추가되었고 다른 SVR4 기반 awk에서 발견되지 않을 수도 있습니다. AIX에서 테스트 할 수 있습니까?)
Stéphane Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.