多数の大きなCSVファイルがあり、それらをTSV(タブ区切り形式)で希望しています。複雑なのは、CSVファイルのフィールドにコンマが含まれていることです。例:
A,,C,"D,E,F","G",I,"K,L,M",Z
期待される出力:
A C D,E,F G I K,L,M Z
(その間の空白は「ハード」タブです)
このサーバーにPerl、Python、およびcoreutilsがインストールされています。
多数の大きなCSVファイルがあり、それらをTSV(タブ区切り形式)で希望しています。複雑なのは、CSVファイルのフィールドにコンマが含まれていることです。例:
A,,C,"D,E,F","G",I,"K,L,M",Z
期待される出力:
A C D,E,F G I K,L,M Z
(その間の空白は「ハード」タブです)
このサーバーにPerl、Python、およびcoreutilsがインストールされています。
回答:
という名前のファイルに追加しcsv2tab.sh
、実行可能にします
#!/usr/bin/env python
import csv, sys
csv.writer(sys.stdout, dialect='excel-tab').writerows(csv.reader(sys.stdin))
$ echo 'A,,C,"D,E,F","G",I,"K,L,M",Z' | ./csv2tab.sh
A C D,E,F G I K,L,M Z
$ ./csv2tab.sh < data.csv > data.tsv && head data.tsv
1A C D,E,F G I K,L,M Z
2A C D,E,F G I K,L,M Z
3A C D,E,F G I K,L,M Z
csv.writer(sys.stdout, dialect='excel-tab').writerows(csv.reader(sys.stdin))
?ループも排除します。
python -c 'import csv,sys; csv.writer(sys.stdout, dialect="excel-tab").writerows(csv.reader(sys.stdin))'
。私-m
はそのようにはたらかないと思う。
お楽しみにsed
。
sed -E 's/("([^"]*)")?,/\2\t/g' file
sed
サポートしていない場合は-E
、を試してください-r
。リテラルタブがsed
サポートさ\t
れていない場合は、リテラルタブ(多くのシェルでctrl- v tab)を配置するか、Bashで$'...'
Cスタイルの文字列を使用してください(この場合、バックスラッシュを\2
2倍にする必要があります)。引用符を保持する場合は、\1
代わりに使用します\2
(この場合、括弧の内側のペアは役に立たず、削除できます)。
これは、二重引用符内のエスケープされた二重引用符を処理しようとしません。一部のCSV方言は、引用符で囲まれた二重引用符(sic)を2倍にすることでこれをサポートしています。
たとえば、csvkit
ユーティリティ(Python)を使用します。
$ csvformat -T in.csv > out.txt
正しいCSVおよびTSVクォートおよびエスケープを使用してストリーミングを行います
aptおよびその他のパッケージマネージャーにあります。
1つのオプションは、perlのText :: CSVモジュールなどです。
perl -MText::CSV -lne 'BEGIN { $csv = Text::CSV->new() }
print join "\t", $csv->fields() if $csv->parse($_)
' somefile
実証する
echo 'A,,C,"D,E,F","G",I,"K,L,M",Z' |
perl -MText::CSV -lne 'BEGIN { $csv = Text::CSV->new() }
print join "\t", $csv->fields() if $csv->parse($_)
'
A C D,E,F G I K,L,M Z
perl -lne '
my $re = qr/,(?=(?:[^"]*"[^"]*")*(?![^"]*"))/;
print join "\t", map { s/(?<!\\)"//gr =~ s/\\"/"/gr } split $re;
'
awk -v Q=\" -v FPAT="([^,]*)|(\"[^\"]+\")" -v OFS="\t" '{
for (i=1; i<=NF; ++i)
if ( substr($i, 1, 1) == Q )
$i = substr($i, 2, length($i) - 2)
print $1, $2, $3, $4, $5, $6, $7, $8
}'
結果:
A C D,E,F G I K,L,M Z
熱核ハエのたたきソリューションでは、libreofficeを使用する必要があります。しばらくhttps://ask.libreoffice.org/en/question/19042/is-is-possible-to-convert-comma-separated-value-csv-to-tab-separated-value-tsv-via-headless-mode /これは不可能であると示唆しているが、間違っている(または単に古い?)ため、次のコマンドは5.3で機能します。
loffice "-env:UserInstallation=file:///tmp/LibO_Conversion" --convert-to csv:"Text - txt - csv (StarCalc)":9,34,UTF8 --headless --outdir some/path --infilter='csv:44,34,UTF8' *.csv
env
引数を省略することができたが、この方法は、文書は、あなたの最近の文書には表示されません。
説明した変換を処理するオープンソースのCSVからTSVへのコンバーターを作成しました。非常に高速で、大きなCSVファイルを変換する必要がある場合は一見の価値があります。ツールは、eBayのTSVユーティリティツールキットの一部です(csv2tsvのドキュメントはこちら)。説明されている入力にはデフォルトのオプションで十分です。
$ csv2tsv file.csv > file.tsv
楽しみのために、Vimで正規表現の置換を実行できます。以下から適応される潜在的な4行のソリューションがあります:https : //stackoverflow.com/questions/33332871/remove-all-commas-between-quotes-with-a-vim-regex
引用符は削除されます。
:%s/".\{-}"/\=substitute(submatch(0), ',', '_' , 'g')/g
:%s/,/\t/g
:%s/_/,/g
:%s/"//g
ソリューションをある程度スクリプト化するには、上記の4行(先頭のコロンはなし)をファイルに保存できます(例:)to_tsv.vim
。で編集するための各CSVを開くのVimとのスクリプトVimの(から適合コマンドライン/programming/3374179/run-vim-script-from-vim-commandline/8806874#8806874)。
source
to_tsv.vim
:source /path/to/vim/filename/to_tsv.vim
jq
ユーティリティを使用してCSVをTSVに変換する例を次に示します。
$ jq -rn '@tsv "\(["A","","C","D,E,F","G","I","K,L,M","Z"])"'
A C D,E,F G I K,L,M Z
または:
$ echo '["A","","C","D,E,F","G","I","K,L,M","Z"]' | jq -r @tsv
A C D,E,F G I K,L,M Z
ただし、CSV形式は適切にフォーマットする必要があるため、各文字列を引用符で囲む必要があります。
出典:シンプルなTSV出力形式。
ではperl
、csvフィールドに埋め込み"
または改行またはタブがないと仮定します。
perl -pe 's{"(.*?)"|,}{$1//"\t"}ge'
以下は、@ tripleeeからの回答に対する単なる修正 であり、他のすべてのフィールドと同様に、最終フィールドから引用符を取り除きます。
何が修正されているかを示すために、以下にトリプリーの回答と、最後の「Z」フィールドの前後に引用符を追加したOPのサンプルデータへのわずかな変更を示します。
echo 'A,,C,"D,E,F","G",I,"K,L,M","Z"' | sed -r -e 's/("([^"]*)")?,/\2\t/g'
A C D,E,F G I K,L,M "Z"
' Z 'が引用符で囲まれていることがわかります。これは、内部フィールドの処理方法とは異なります。たとえば、「G」には引用符がありません。
次のコマンドは、2番目の置換を使用して最終列を消去します。
echo 'A,,C,"D,E,F","G",I,"K,L,M","Z"' | sed -r -e 's/("([^"]*)")?,/\2\t/g' \
-e 's/\t"([^"]*)"$/\t\1/'
A C D,E,F G I K,L,M Z
'A,,C,"D,E,F","G",I,"K,L,M","Z,A"'
がこの回答に入力される"Z,A"
とZ A
、はでなくで誤って置き換えられますZ,A
。