各フィールドがコンマで区切られた以下のファイルがあります。 5番目のフィールド("txt4 "(tst)""
)を変更し、"
2つの外部引用符を除いて、そのフィールドのすべての項目をに置き換える必要がありますchr(34)
。つまり、最後のフィールドはに変換する必要があります"txt4 chr(34)(tst)chr(34)"
。実際のデータには、ここに示されているフィールドよりも多くのフィールドを含めることができるため、ソリューション内の特定のフィールドをリストすることは非現実的です。
以下の出力を取得するには、awkを使用する必要があります。
サンプルcsvファイル:
"this is txt1","this is txt2",3,"this txt3","txt4 "(tst)""
希望の出力:
"this is txt1","this is txt2",3,"this txt3","txt4 chr(34)(tst)chr(34)"
答え1
データのソースまたは予想される形式については実際にはあまり話しません。練習を「replace with "(
」または「replace with」に再構成できる場合は、次の2つのコマンドを使用できます。chr(34)(
")
)chr(34)
"(tst)"
chr(34)(tst)chr(23)
sed
$ sed -e 's/"(/chr(34)(/' -e 's/)"/)chr(34)/' file
"this is txt1","this is txt2",3,"this txt3","txt4 chr(34)(tst)chr(34)"
$ sed 's/"\((tst)\)"/chr(34)\1chr(34)/' file
"this is txt1","this is txt2",3,"this txt3","txt4 chr(34)(tst)chr(34)"
最後のフィールドの形式が正しくないため、テキストをCSVレコードに解析できません。このフィールドの正しく引用されたバージョンは次のとおりです"txt4 ""(tst)"""
。
答え2
ここでは、有効なCSVフィールド引用符が行の先頭、行の終わり、またはカンマの横にあることがわかります。したがって、各引用符とその両方の文字を検索してください。両方ともカンマでない場合は、引用符が2倍になります。
これは絶対に真実ではありません。有効なCSVでは、引用符の中にカンマを含めることができます(たとえば、「one field」、「here」)。ただし、これはお客様のデータに適用されます。
テスト:
Paul--) ./awkFixCsv
"this is txt1","this is txt2",3,"this txt3","txt4 "(tst)"" <<< Input
"this is txt1","this is txt2",3,"this txt3","txt4 ""(tst)""" <<< Output
"this is txt1","this is txt2",3,"this txt3","txt4 "(tst)"",""","""","done" <<< Input
"this is txt1","this is txt2",3,"this txt3","txt4 ""(tst)""","""","""""","done" <<< Output
One,Two,"3","Four","Five "and" Six",Seven and Eight,"Nine" <<< Input
One,Two,"3","Four","Five ""and"" Six",Seven and Eight,"Nine" <<< Output
Paul--)
コード、テストデータをここに文書化し、関数に変更します。これをスクリプトに統合する方法がわからない場合は、コメントを残してください。
#! /bin/bash
AWK='
function Fix (s, Local, t, u, x) {
while (match (s, ".\042.")) {
u = substr (s, RSTART, RLENGTH);
x = (u ~ /..,/ || u ~ /,../) ? 0 : 1;
t = t substr (s, 1, RSTART + x);
s = substr (s, RSTART + 1);
}
return (t s);
}
{ print "\n" $0 " <<< Input"; }
{ $0 = Fix( $0); }
{ print $0 " <<< Output"; }
'
awk "${AWK}" <<[][]
"this is txt1","this is txt2",3,"this txt3","txt4 "(tst)""
"this is txt1","this is txt2",3,"this txt3","txt4 "(tst)"",""","""","done"
One,Two,"3","Four","Five "and" Six",Seven and Eight,"Nine"
[][]
答え3
真珠テキスト::CSVこのモジュールは、このような誤った形式のCSVを処理するのに非常にうまくいきます。特に:
CSVデータが本当に悪い場合。
1,"foo "bar" baz",42 or 1,""foo bar baz"",42
このデータ行を解析し、引用符付きフィールド内で引用符を残す方法はありますか?これはAllow_loose_quotesを設定し、escape_charがquote_charと等しくないようにすることで達成できます。
例えば
$ echo '"this is txt1","this is txt2",3,"this txt3","txt4 "(tst)""' | perl -MText::CSV -lne '
BEGIN{$p = Text::CSV->new({escape_char => "", allow_loose_quotes => 1, quote_space => 1})}
@row = $p->fields() if $p->parse($_);
$p->escape_char("\""); $p->print(*STDOUT,\@row);
'
"this is txt1","this is txt2",3,"this txt3","txt4 ""(tst)"""