sed
awk
、またはperl -n
入力処理などのツール記録一度、記録存在するワイヤー基本的に。
awk
with RS
、 GNU sed
with -z
、perl
with などの一部では、-0ooo
別のレコード区切り文字を選択してレコードの種類を変更できます。
perl -n
入力全体(複数のファイルを渡す場合は個々のファイル)を1つのファイルにすることができます。記録オプションがある場合-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
これはただ1文字で、/もRS
なく、変数もなく、通常NUL文字を処理できません。BEGINFILE
ENDFILE
RT
RS='\0'
とにかく、NULバイトを含む入力を処理できないため、使用すると動作すると思うかもしれませんが、そうではありません。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
このアプローチのもう1つの問題は、ファイルが改行文字で終わらず空でない場合は、$0
ファイルがまだ最後にランダムに追加されることです(上記のコードでは代わりにgawk
使用できます)。 1つの利点は、/にファイルの行数を記録することです。RT
RS
NR
FNR
一度に複数のファイルを処理するには、単一のステートメントからすべてのファイルを手動で読み取ることですBEGIN
(ここでは、70年代のAPIを使用するSolarisawk
ではなく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
末尾改行についても同じ警告です。このファイルの利点は、=
文字を含むファイル名を処理できることです。