我有一个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"
您似乎在示例输出中也删除了空格?