같은 도구 sed
를 사용 awk
하거나 perl -n
한 번에 한 레코드 씩 입력을 처리합니다 . 기본적으로 레코드 는 행 입니다.
awk
with RS
, sed
with -z
또는 perl
with 와 같은 일부 -0ooo
는 다른 레코드 구분 기호를 선택하여 레코드 유형을 변경할 수 있습니다.
perl -n
전체 입력을 하나의 (여러 파일을 통과 한 각 개별 파일) 할 수 있습니다 기록 와 -0777
(또는 옵션 -0
777은 정규 하나되고, 0377보다 8 진수의 큰 다음을). 그것이 그들이 slurp mode 라고 부르는 것 입니다.
비슷한 일을 함께 할 수 awk
의 RS
또는 다른 어떤 메커니즘? awk
각 파일의 각 줄 과 반대로 각 파일 내용을 전체적으로 처리하는 위치는 어디 입니까?
답변
단일 문자 (전통적인 구현 과 같은 ) 또는 정규식 (같은 또는 수행)으로 awk
취급 되는지에 따라 다른 접근 방식을 취할 수 있습니다 . 빈 파일도 건너 뛰는 경향이 있는 것으로 간주하기 까다 롭습니다 .RS
awk
gawk
mawk
awk
gawk
, mawk
또는 다른 awk
구현 예는 어디 RS
regexp와 수있다.
이러한 구현에서 ( 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
입니다.