列値の前にアポストロフィ( ')を追加するには?

列値の前にアポストロフィ( ')を追加するには?

複数の列と1000のレコードを含むCSVファイルがあり、列の1つ(2番目の列であると仮定)のすべての値の前にアポストロフィを追加する必要があります。'最初の行やヘッダー行に加えて、単純な行があるかもしれません。awkまたはを使用してどのようにこれを達成できますかsed?二重引用符で囲まれた値には、複数のカンマを含めることができます。

サンプル:

"col1","col2","col3","col4","col5"
"value11","value12","value13","value14","value15"
"value21","value22","value23","value24","value25"
"value31","value32","value33","value34","value35"

予想出力:

"col1","col2","col3","col4","col5"
"value11","'value12","value13","value14","value15"
"value21","'value22","value23","value24","value25"
"value31","'value32","value33","value34","value35"

答え1

sed:

sed '2,$s/^\("[^"]*","\)/\1'"'"/ test.in

一部のエスケープを削除するには、ERE を使用します。

sed -E '2,$s/^("[^"]*",")/\1'"'"/ test.in

奇妙な:

awk -F, 'NR>1{sub(/^"/,"\"'"'"'",$2)}1' test.in

引用を心配しない場合は、エスケープコードを使用してください。

awk -F, '{sub(/^"/,"\"\x27",$2)}1' test.in

答え2

パールの使用:

perl -pi -e '
             BEGIN{
                 $column_number = 2; # Change as needed
                 $column_number--;
                 $apostrophe = chr 39;
             }
             next unless $this_is_data++; # Skip the first line
             s@ ^((?:"[^"]+"\s*,){$column_number}) "@$1"$apostrophe@x
           ' your_file

これは、フィールドにバックスラッシュでエスケープされた引用符が含まれていないと仮定します。

答え3

愚か者の使い方は次のとおりです。

$ gawk -F'","' -v var="'" -v OFS='","' 'NR>1{$2=var$2;} 1' foo.csv 

この-vオプションを使用すると、スクリプトにアクセスできる変数を定義できますgawk。この場合、varis'OFS(出力フィールド区切り記号)は","入力フィールド区切り記号(-F)と同じです。次に、これが最初の行()ではないことを確認し、2番目の列にNR>1値を追加します。var結局、これは1ただのトリックであり、真と評価され、対応する行gawkが印刷されます。 1つを追加するのと同じですprint;が、短いです。

別の列でこれを実行するには、$2=var$2;目的の列番号に変更するだけです$N=var$NN


Perlでもこれを行うことができます(もちろん、次のようにすることもできます)。すべてパールから):

$ perl -F'\",\"' -ane '$.>1 && do{$F[1]=chr(39).$F[1]}; 
                       print join("\",\"",@F)' foo.csv

この-aスイッチは、perlがgawkのように入力ラインを分割し、単に配列に格納するようにします(perl配列は0から始まるので、2番目の列は、3番目の列は等に@Fなります)。 (再度同様) 入力フィールドの区切り記号を設定します。したがって、行番号が1()より大きいことを確認し、そうであれば(a、thanks @josephR)値を追加します。最後に、結果文字列を使用して配列の各要素を連結して印刷します。$F[1]$F[2]-Fgawk$.>1chr 39'join@F","

答え4

簡単な方法はsed次のとおりです。

$ sed 's/","/","\x27/' afile
"col1","'col2","col3","col4","col5"
"value11","'value12","value13","value14","value15"
"value21","'value22","value23","value24","value25"
"value31","'value32","value33","value34","value35"

詳細

私たちは最初の発生を検索し、","それに置き換えます","`。しかし、バックティックをエスケープするのは難しいかもしれません。したがって、対応する16進エスケープコードを入力するだけです\x27

あなたの問題

必要な行だけを変更するように制限するために、このように調整できます。

$ cat <(head -n +1 afile) <(tail -n +2 afile | sed 's/","/","\x27/')
"col1","col2","col3","col4","col5"
"value11","'value12","value13","value14","value15"
"value21","'value22","value23","value24","value25"
"value31","'value32","value33","value34","value35"

sedあるいは、ヒント8-)を知っている場合は、最初の行を完全にスキップできます。

$ sed '2,$s/","/","\x27/' afile
"col1","col2","col3","col4","col5"
"value11","'value12","value13","value14","value15"
"value21","'value22","value23","value24","value25"
"value31","'value32","value33","value34","value35"

これはsed、最後の行($)までの2番目の行を選択し、検索と置換で実行することを意味します。

関連情報