CSVファイルを処理する前に、列数を確認したいと思います。問題は、一部のフィールドのテキストに区切り文字(カンマ)が表示され、正しく解析できず、列が多すぎるということです。
たとえば、
~new file: 12345~,~125.5~,,,~ example (45), case (20)~,,
7列
~new file: 12345~
~125.5~
- 空
- 空
~ example (45), case (20)~
- 空
- 空
問題は~example (45), case (20)~
5番目の列のカンマです。
,
;
区切り文字をusingに置き換えようとしましたが、何度も繰り返す必要sed
があります。
私は、より最適化された方法で複数のケースを一致させるための一般的な規則が欲しいです。
フィールド参照文字が~
あります(a, b, c, d
4つのフィールドにも同じですa, ~b, c~, d
が、3つのフィールドの1つはb, c
)。
サンプル:
~new file: 12345~,~125.5~,,,~ example (45), case (20)~,,
~file (54) ~,,~5.5~,,~ this is a sample.~,,~end, end~
~line 3~,~3.6~,~0.0~,~hello~,~hello, world~,~6.7~,~end of line~
予想出力:
~new file: 12345~;~125.5~;;;~ example (45), case (20)~;;
~file (54) ~;;~5.5~;;~ this is a sample.~;;~end, end~
~line 3~;~3.6~;~0.0~;~hello~;~hello, world~;~6.7~;~end of line~
答え1
これは、カンマをフィールド区切り文字として使用し、チルダを引用符として使用するCSVファイルのように見えます。
Perlモジュールが提供するものなど、正しいCSVパーサーを使用してくださいText::CSV
。
perl -MText::CSV -e 'print scalar(@{Text::CSV->new({quote_char=>"~"})->getline(\*STDIN)})' <file.csv
その後、CSVファイルの最初の行を読み取り、file.csv
その中の列数を印刷します。最初の行を読むために引用符を使用する前にチルダ文字であることを理解するパーサーをインスタンス化します。このパーサのメソッドは、getline()
指定されたファイルハンドルから行を読み取り、データ配列への参照を返します(解析された各列に1つの項目)。これはprint scalar(...)
Perlで配列の長さを印刷する非常に一般的な方法です。
別の方法はCSVキットコマンドラインCSVパーサーツールキット:
csvstat -n -q '~' <file.csv | wc -l
または、均等に長いオプションを使用すると、
csvstat --names --quotechar '~' <file.csv | wc -l
また、入力ファイルの最初の行を読み取り、ヘッダーリスト(CSVファイルの最初の行には通常列ヘッダーが含まれています)を1行に1つずつ返します。wc -l
返された行数を計算します。
コマンドcsvstat
自体は(なしでwc -l
)返されます。
1: new file: 12345
2: 125.5
3:
4:
5: example (45), case (20)
6:
7:
後でCSVファイルを解析するときは、次のいずれかの方法を使用するか、最も快適なプログラミング言語に適したパーサーを見つけることをお勧めします。awk
そして、sed
次の用途に使用できます。シンプルCSVデータですが、この場合、データは注意しないと、これらのツールが扱いにくい一部のCSV形式機能を使用します。
答え2
修正された質問に対する回答:
sed -r 's/(~[^~]*~)?,/\1;/g' infile
~new file: 12345~;~125.5~;;;~ example (45), case (20)~;;
~file (54) ~;;~5.5~;;~ this is a sample.~;;~end; end~
~line 3~;~3.6~;~0.0~;~hello~;~hello, world~;~6.7~;~end of line~
すべてをwhere~...~,
に置き換えることはオプションです。~...~;
~...~
各行の列数を数えるには、awk
次のようにします。
awk -F, '{ gsub(/~[^~]*~/,""); print NF }' infile
次の入力の場合:
~new file: 12345~,~125.5~,,,~ example (45), case (20)~,,
,~125.5~,,,~ example (45), case (20)~
次を返します。
7
5
では、gsub(/~[^~]*~/,"")
aから始めて、次のパターンまで空の文字列に置き換えます。~
~
~...~
awk -F, '{ gsub(/~[^~]*~/,""); print $0 }' infile
,,,,,,
,,,,
これは入力に内部アナログがないと仮定します~
。,~some~thing~,
これにより、print NF
指定されたフィールド区切り文字に従ってフィールド数が印刷されます-F
。
答え3
,
column
列の区切り記号。次のようにコマンドを実行します。
column -s',' -t -o',' original_data.txt > output.csv
説明する