sed
awk
, 또는 perl -n
입력 처리 와 같은 도구기록한 번,기록존재하다철사기본적으로.
awk
with RS
, GNU sed
with -z
또는 perl
with 와 같은 일부는 -0ooo
다른 레코드 구분 기호를 선택하여 레코드 유형을 변경할 수 있습니다.
perl -n
전체 입력(여러 파일을 전달할 경우 각 개별 파일)을 하나의 파일로 만드는 것이 가능합니다.기록옵션이 있는 경우 -0777
(또는 -0
0377보다 큰 8진수가 뒤따르며, 777이 표준임) 그게 그들이 말하는 거야흡연 모드.
awk
이나 다른 메커니즘을 사용하여 RS
유사한 작업을 수행 할 수 있습니까? 각각 awk
을 처리하는문서내용은 순서가 아닌 순서대로 배열되어 있습니다.철사파일마다?
답변1
단일 문자로 awk
처리하는지 (기존 구현에서와 같이) 정규 표현식으로 처리하는지(like 또는 do) 에 따라 다양한 접근 방식을 취할 수 있습니다 . 빈 파일은 건너뛰는 경향이 있기 때문에 고려하기 어렵습니다 .RS
awk
gawk
mawk
awk
gawk
, 또는 mawk
정규 표현식이 될 수 있는 다른 awk
구현 입니다 RS
.
이러한 구현에서( 의 경우 mawk
일부 운영 체제(예: Debian)는 대신 매우 오래된 버전을 릴리스합니다.@ThomasDickey가 관리하는 최신 버전), RS
단일 문자가 포함된 경우 레코드 구분 기호는 해당 문자이고, 비어 있으면 awk
단락 모드로 들어가고 RS
, RS
그렇지 않으면 정규식으로 처리됩니다.
해결책은 일치가 불가능한 정규식을 사용하는 것입니다. 일부는 x^
또는 $x
( x
시작 전 또는 끝 후)를 좋아합니다. 그러나 일부는 (특히 gawk
) 다른 것보다 더 비쌉니다. 지금까지 나는 이것이 ^$
가장 효과적인 방법이라는 것을 알았습니다. 빈 입력만 일치할 수 있지만 일치하는 항목이 없습니다.
그래서 우리는 이렇게 할 수 있습니다:
awk -v RS='^$' '{printf "%s: <%s>\n", FILENAME, $0}' file1 file2...
그러나 빈 파일을 건너뛴다는 점에 유의하세요(반대 perl -0777 -n
). GNU는 awk
코드를 명령문에 넣어 ENDFILE
이 문제를 해결할 수 있습니다. 그러나 BEGINFILE 문에서도 이를 재설정해야 합니다 $0
. 그렇지 않으면 빈 파일을 처리한 후에 재설정되지 않습니다.
gawk -v RS='^$' '
BEGINFILE{$0 = ""}
ENDFILE{printf "%s: <%s>\n", FILENAME, $0}' file1 file2...
전통적인 awk
구현, POSIXawk
이는 단지 하나의 문자이고 /도 RS
없고 변수도 없으며 일반적으로 NUL 문자를 처리할 수 없습니다.BEGINFILE
ENDFILE
RT
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
한 번에 여러 파일을 처리하려면 한 가지 방법은 단일 명령문에서 모든 파일을 수동으로 읽는 것입니다 BEGIN
(여기서는 70년대 API를 사용하는 Solaris awk
가 아니라 POSIX를 가정)./bin/awk
awk -- '
BEGIN {
for (i = 1; i < ARGC; i++) {
FILENAME = ARGV[i]
$0 = ""
while ((getline line < FILENAME) > 0)
$0 = $0 line "\n"
# actual processing here, example:
print i". "FILENAME" has "NF" fields and "length()" characters."
}
}' *.txt
후행 개행에 대한 동일한 경고입니다. 이 파일의 장점은 =
문자가 포함된 파일 이름을 처리할 수 있다는 것입니다.