awk:NULをレコード区切り文字として使用しないフィールドの正確な文字列一致

awk:NULをレコード区切り文字として使用しないフィールドの正確な文字列一致

フィールドに改行(二重引用符で囲む)を含むファイルがある場合は、NULをレコード区切り文字として使用し、目的のレコードを選択しようとします。そのために、行末をNULに変更し、改行で区切られたフィールドを修正しました(完成を使用sed)。ただし、最初のフィールドawkと文字列(GNU)の正確な一致は失敗します。興味深いことに、最初のフィールドで文字列パターンの一致が失敗するため、RS="\x00"アプリケーションは正しいと考えられます。

なぜ失敗したのですか?パターンマッチングが機能するのはなぜですか?

サンプルファイルinput.txt:

head1,head2,head3
a,b,c
b,no a in first field,c
a,"with quotes",c
a,"with ,",c
b,a,1
a,"with
 newline",c
b,1,a

awkNUL操作を導入する前に、正確な文字列で選択内容を記録してください。

$awk 'BEGIN {FS=OFS=","} {if ($1=="a") print}' input.txt

結果:

a,b,c
a,"with quotes",c
a,"with ,",c
a,"with

NULを導入し、「newline-splits」アクションを修正する("with\n newline"エントリを参照):

$sed -e 's/$/\x00/' -e 's/\(,"[^,"]*\)\x00/\1/' input.txt | cat -A

head1,head2,head3^@$
a,b,c^@$
b,no a in first field,c^@$
a,"with quotes",c^@$
a,"with ,",c^@$
b,a,1^@$
a,"with$
 newline",c^@$
b,1,a^@$

フィールド1でパターンマッチングを使用すると機能します("a"他のフィールドではどのように失敗しますが、"head1"一致するかを参照)。

$sed -e 's/$/\x00/' -e 's/\(,"[^,"]*\)\x00/\1/' input.txt |
awk 'BEGIN {RS=ORS="\x00" ; FS=OFS=","}
     { if ($1~"a") print}' |
cat -A

head1,head2,head3^@$
a,b,c^@$
a,"with quotes",c^@$
a,"with ,",c^@$
a,"with$
 newline",c^@

しかし、:フィールド1の正確な一致に"a"失敗しました:

sed -e 's/$/\x00/' -e 's/\(,"[^,"]*\)\x00/\1/' input.txt |
awk 'BEGIN {RS=ORS="\x00" ; FS=OFS=","} { if ($1=="a") print}' 

##<no output>##

私はどこで間違っていますか?以前はNULをジョブとして使用するのはなぜですかRS

ベストアンサー1

sedコマンドは、\n改行()をNUL(\0)に変更せずにNUL +改行(\0\n)に変更します(cat -A図を参照)。

GNU awkを使用してRSをに設定すると、\0後続のレコード(および最初のフィールド)の最初の文字が加算され、正確な\n一致が中断されます。

改行's/\(,"[^,"]*\)\x00/\1/'分割修正はこれをまったく変更しません。 newline",c以前のレコードにレコードを追加するだけです。


高速で汚れた「解決策」は、単にセットではなくRS設定することです。しかし、awkが解析できるようにcsvファイルを処理するこの方法は信頼できないため、実際にはより良いものを見つける必要があります。\0\n\0

最後の例を使用して:

sed -e 's/$/\x00/' -e 's/\(,"[^,"]*\)\x00/\1/' input.txt |
gawk 'BEGIN {RS=ORS="\x00\n" ; FS=OFS=","} { if ($1=="a") print}' | cat -A
a,b,c^@$
a,"with quotes",c^@$
a,"with ,",c^@$
a,"with$
 newline",c^@$
sed -e 's/$/\x00/' -e 's/\(,"[^,"]*\)\x00/\1/' input.txt |
gawk 'BEGIN {RS="\x00\n" ; FS=OFS=","} { if ($1=="a") print}'
a,b,c
a,"with quotes",c
a,"with ,",c
a,"with
 newline",c

おすすめ記事