用垂直线替换文本文件中的逗号,引号除外

用垂直线替换文本文件中的逗号,引号除外

我有一个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

csvformat是 csvkit 的一部分: 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 的最稳健方法是什么

仅用于您向我们展示的输入,并在删除字段分隔符逗号周围的空格并将 RS 设置为 后使用 GNU awk 进行 FPAT,\r\n因为您的输入文件具有 DOS 行结尾:

$ 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"

当通过加倍引用 时,这应该起作用",如"""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

一种方法是将双引号内的逗号更改为文本中未使用的某些字符,将所有其他逗号更改为目标字符,然后将标记更改回逗号:

$ 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"

您似乎在示例输出中也删除了空格?

相关内容