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