awkを使用して二重引用符を置き換える

awkを使用して二重引用符を置き換える

各フィールドがコンマで区切られた以下のファイルがあります。 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)"""

関連情報