引用符を除いて、テキストファイルのコンマを縦線で置き換えます。

引用符を除いて、テキストファイルのコンマを縦線で置き換えます。

txtファイルがあります。

 ,"Hi, I am Tom",,"16"
"I3","Hi, I am Jerry","Mouse","17"

ここでファイルは UTF-8 です。私がしたいのは、引用符 ""内の内容を除いてコンマを|に置き換えることです。したがって、新しく作成されたtxtファイルは次のようになります。

|"Hi, I am Tom"||"16"
"I3"|"Hi, I am Jerry"|"Mouse"|"17"

私はsedまたはawkスクリプトについてはよくわかりませんが、これを行うために使用できると聞きました。誰でもそれがどのように完了したのか教えてもらえますか?

答え1

Edのコメントに従い、カンマの周りのスペースを編集すると

$ cat text.csv
,"Hi, I am Tom",,"16"
"I3","Hi, I am Jerry","Mouse","17"

$ csvformat -D '|' text.csv
|Hi, I am Tom||16
I3|Hi, I am Jerry|Mouse|17

csvformatcsvkitの一部です。 https://csvkit.readthedocs.io/en/1.0.2/scripts/csvformat.html


CSVモジュールには、Rubyなど、ユーザーがインストールした可能性がある他の言語が付属しています。

$ ruby -rcsv -e 'CSV.foreach(ARGV.shift) {|row| puts CSV.generate_line(row, col_sep: "|")}' text.csv
|Hi, I am Tom||16
I3|Hi, I am Jerry|Mouse|17

答え2

これは一般的なCSVの問題です。awkを使用してcsvを効率的に解析する最も強力な方法は何ですか

表示された入力に対してのみ\r\n入力ファイルにDOS行の終わりがあるため、フィールド区切り文字のコンマの周囲のスペースを削除してRSをに設定し、FPATにGNU awkを使用します。

$ cat -v file
,"Hi, I am Tom",,"16"^M
"I3","Hi, I am Jerry","Mouse","17"^M

$ awk -v RS='\r\n' -v FPAT='[^,]*|"[^"]+"' -v OFS='|' '{NF; $1=$1} 1' file
|"Hi, I am Tom"||"16"
"I3"|"Hi, I am Jerry"|"Mouse"|"17"

これはNF;gawk 5.0.1の現在のバグを解決するためのものです。https://lists.gnu.org/archive/html/bug-gawk/2019-11/msg00003.html

もちろん、今自分に聞いてみなければなりません。引用符付きフィールドに|s、エスケープされた二重引用符(""または)、または改行文字が含まれている場合は\"どうすればよいですか?

答え3

@RudiCのアイデアを拡張すると、次のようになります。

awk -v RS='"' -v ORS= '{if(NR % 2){gsub(",","|"); print} else print RS $0 RS}' file

 | "Hi, I am Tom"||"16"
"I3"| "Hi, I am Jerry"|"Mouse"|"17"

これは、(完了した方法)"のように2倍に参照するときに機能します。"""Hi, I am Tom"", said the DOG"基準CSV)、バックスラッシュでエスケープされた場合ではありません。引用符付きテキストと引用符付きテキストを交互に使用することに加えて、ファイル形式は重要ではなく、有効なCSVである必要はありません。

GNU gawk( gawk) を使用すると、次のように単純化できます。

gawk -v RS='"' -v ORS= 'NR % 2 {gsub(",","|")} {print $0 RT}' file

同じことperl:

perl -pe 'BEGIN{$/=q/"/} s/,/|/ if $. % 2' file

答え4

1つの方法は、二重引用符内のコンマをテキストに使用されていない一部の文字に変更し、他のすべてのコンマをターゲット文字に変更してからトークンを再度コンマに変更することです。

$ awk -F'"' '
        {for (i=2; i<=NF; i+=2) gsub (/,/, "\001", $i)
         gsub (/,/, "|")
         gsub (/\001/, ",")
        }
1
' OFS='"' file
 | "Hi, I am Tom"||"16"
"I3"| "Hi, I am Jerry"|"Mouse"|"17"

例の出力でも空白を削除していると思いますか?

関連情報