二重引用符以外のすべてのカンマをパイプに置き換えます。

二重引用符以外のすべてのカンマをパイプに置き換えます。

sedを使用して二重引用符以外のすべてのカンマをパイプに置き換えたいと思います。

したがって、.csv ファイルの次の行は次のようになります。

John,Tonny,"345.3435,23",56th Street

次のように変換されます。

John|Tonny|"345.3435,23"|56th Street

この問題を解決するために正規表現を助けることができますか?

答え1

使用csvkit:

$ csvformat -D '|' file.csv
John|Tonny|345.3435,23|56th Street

csvkitのツールは、複雑なCVSファイルを処理する方法を知っており、ここではcsvformat区切りコンマを正しい方法で置き換えます|。出力フィールドは必要に応じて参照されます。

例:

$ cat file.csv
John,Tonny,"345.3435,23",56th Street
The | factory,Ltd.,"0,0",meep meep

$ csvformat -D '|' file.csv
John|Tonny|345.3435,23|56th Street
"The | factory"|Ltd.|0,0|meep meep

答え2

sedこのオプションをサポートしている場合-E-r一部の実装では):

sed -Ee :1 -e 's/^(([^",]|"[^"]*")*),/\1|/;t1' < file

これ

:label
   s/pattern/replacement/
t label

非常に一般的なsed慣用語です。成功する限り、ループで同じ置換を続けます。

ここでは"、ゼロ個以上の引用符で囲まれた文字列または文字(でキャプチャされる)以外の文字で構成される行の先頭を対応するキャプチャとaで置き換えます。したがって、あなたの例では、次のことを意味します。,\1,\1|

  • John,Tonny,"345.3435,23",56th Street->John|Tonny,"345.3435,23",56th Street
  • John|Tonny,"345.3435,23",56th Street->John|Tonny|"345.3435,23",56th Street
  • John|Tonny|"345.3435,23",56th Street->John|Tonny|"345.3435,23"|56th Street
  • パターンが一致しなくなったので、ここで停止します。

を使用するには、perlフラグを次のように置き換えますg

perl -pe 's{("[^"]*"|[^",]+)|,}{$1 // "|"}ge'

ここで、入力の引用符がバランスを取っていると仮定すると、パターンはすべての入力と一致して次のように分類されます。

  • 引用符付き文字列
  • ,または以外の文字シーケンス"
  • カンマ

そして、一致する文字列がコンマの場合にのみ$1置き換えられます(replaceセクションで定義されていない場合)|

答え3

パールを使って

perl -MText::CSV -lne '
  BEGIN { $p = Text::CSV->new() } 
  print join "|", $p->fields() if $p->parse($_)
' file.csv
John|Tonny|345.3435,23|56th Street

答え4

Pythonとcsvモジュールの使用:

import csv,sys

with open(sys.argv[1]) as csvfile:
    csvr = csv.reader(csvfile)
    for line in csvr:
        dup = map( lambda x: '"' + x + '"' if ',' in x else x, line )
        print('|'.join(dup))

仕組みは次のとおりです。

$ python3 csvfile.py  input.csv 
John|Tonny|"345.3435,23"|56th Street
John|Doe|"123.456,25"|26th Street
Jane|Doe|"987.654,52"|15th Street

関連情報