フィールドに改行(二重引用符で囲む)を含むファイルがある場合は、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
awk
NUL操作を導入する前に、正確な文字列で選択内容を記録してください。
$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