単一の文字(従来の実装のように)としてawk
扱うか、正規表現(like またはdo)RS
として扱うかに応じて、異なるアプローチを取ることができます。空のファイルは、スキップする傾向があると見なされるのも難しいです。awk
gawk
mawk
awk
gawk
、mawk
または正規表現になりうる他のawk
実装RS
。
これらの実装では(のためのmawk
DebianのようないくつかのOSは非常に古いバージョンの代わりに、出荷することに注意してください、@ThomasDickeyによって維持近代的なものを)、あればRS
単一の文字が含まれているレコードセパレータは、その文字である、またはawk
とき段落モードに入りRS
、空でありますRS
それ以外の場合は正規表現として扱います。
そこでの解決策は、一致する可能性のない正規表現を使用することです。x^
または$x
(x
開始前、または終了後)のように思い浮かぶ人もいます。ただし、一部(特にgawk
)は、他よりも高価です。これまでのところ、これが^$
最も効率的な方法であることがわかりました。空の入力でのみ一致しますが、一致するものは何もありません。
できること:
awk -v RS='^$' '{printf "%s: <%s>\n", FILENAME, $0}' file1 file2...
ただし、1つの注意点は、空のファイルをスキップすることです(とは反対perl -0777 -n
)。代わりにステートメントにawk
コードを入れることで、GNUで対処できますENDFILE
。しかし$0
、空のファイルを処理した後はリセットされないため、BEGINFILEステートメントでリセットする必要もあります。
gawk -v RS='^$' '
BEGINFILE{$0 = ""}
ENDFILE{printf "%s: <%s>\n", FILENAME, $0}' file1 file2...
従来のawk
実装、POSIXawk
それらでRS
は、たった1文字であり、BEGINFILE
/ ENDFILE
を持たず、RT
変数を持たず、通常はNUL文字を処理できません。
RS='\0'
とにかく、NULバイトを含む入力を処理できないため、using は機能すると考えられますが、いいえ、RS='\0'
従来の実装ではRS=
段落モードであるとして扱われます。
解決策の1つは、などの入力で検出されそうにない文字を使用することです\1
。マルチバイト文字ロケールでは$'\U10FFFE'
、UTF-8ロケールのように、割り当てられていない文字または非文字を形成するため、発生する可能性が非常に低いバイトシーケンスにすることもできます。しかし、絶対に万全ではなく、空のファイルにも問題があります。
別の解決策は、入力全体を変数に保存し、最後にENDステートメントで処理することです。ただし、一度に処理できるファイルは1つだけです。
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
、上記のコード)。1つの利点は、ファイルの行数の記録がNR
/にあることFNR
です。