我有一个文字文件,里面装满了几行:
Female,"$0 to $25,000",Arlington Heights,0,60462,ZD111326,9/18/13 0:21,Disk Drive
我正在尝试将所有逗号,
更改为管道|
,但引号中的逗号除外。
试图使用sed(我是新手)......它不起作用。使用:
sed '/".*"/!s/\,/|/g' textfile.csv
有什么想法吗?
答案 0 :(得分:1)
作为测试用例,请考虑以下文件:
Female,"$0 to $25,000",Arlington Heights,0,60462,ZD111326,9/18/13 0:21,Disk Drive
foo,foo,"x,y,z",foo,"a,b,c",foo,"yes,no"
"x,y,z",foo,"a,b,c",foo,"yes,no",foo
这是一个sed
命令,用管道符号替换非引用的逗号:
$ sed -r ':a; s/^([^"]*("[^"]*"[^"]*)*),/\1|/g; t a' file
Female|"$0 to $25,000"|Arlington Heights|0|60462|ZD111326|9/18/13 0:21|Disk Drive
foo|foo|"x,y,z"|foo|"a,b,c"|foo|"yes,no"
"x,y,z"|foo|"a,b,c"|foo|"yes,no"|foo
这会查找出现在双引号的对之后的逗号,并用竖线符号替换它们。
:a
这定义了标签a
。
s/^([^"]*("[^"]*"[^"]*)*),/\1|/g
如果行上的逗号前面有0,2,4或任何偶数引号,则用管道符号替换该逗号。
^
这在行的开头匹配。
(`
这将启动主要分组(\1
)。
[^"]*
这会查找零个或多个非引号字符。
("[^"]*"[^"]*)*
parens外面的*
意味着我们正在寻找parens中的零个或多个模式。 parens中的模式包括引号,任意数量的非引号,引号以及非引号上的任何数字。
换句话说,此分组仅匹配引号的对。由于parens之外的*
,它可以匹配任何偶数引号。
)
这将关闭主要分组
,
这要求分组后跟逗号。
t a
如果上一个s
命令成功替换,则test
命令会让sed
跳回标签a
并重试。
如果没有替换,那么我们就完成了。
答案 1 :(得分:0)
使用awk可能是eaiser:
kent$ cat f
foo,foo,"x,y,z",foo,"a,b,c",foo,"yes,no"
Female,"$0 to $25,000",Arlington Heights,0,60462,ZD111326,9/18/13 0:21,Disk Drive
kent$ awk -F'"' -v OFS='"' '{for(i=1;i<=NF;i++)if(i%2)gsub(",","|",$i)}7' f
foo|foo|"x,y,z"|foo|"a,b,c"|foo|"yes,no"
Female|"$0 to $25,000"|Arlington Heights|0|60462|ZD111326|9/18/13 0:21|Disk Drive
答案 2 :(得分:0)
我建议使用适当的CSV解析器的语言。例如:
ruby -rcsv -ne 'puts CSV.generate_line(CSV.parse_line($_), :col_sep=>"|")' file
Female|$0 to $25,000|Arlington Heights|0|60462|ZD111326|9/18/13 0:21|Disk Drive
答案 3 :(得分:0)
我会使用gnu awks
FPAT
。它定义了一个字段如何显示FS
,告诉分隔符是什么。然后,您可以将输出分隔符设置为|
awk '{$1=$1}1' OFS=\| FPAT="([^,]+)|(\"[^\"]+\")" file
Female|"$0 to $25,000"|Arlington Heights|0|60462|ZD111326|9/18/13 0:21|Disk Drive
如果您的awk
不支持FPAT
,则可以使用:
awk -F, '{for (i=1;i<NF;i++) {c+=gsub(/\"/,"&",$i);printf "%s"(c%2?FS:"|"),$i}print $NF}' file
Female|"$0 to $25,000"|Arlington Heights|0|60462|ZD111326|9/18/13 0:21|Disk Drive
答案 4 :(得分:0)
sed 's/"\(.*\),\(.*\)"/"\1##HOLD##\2"/g;s/,/|/g;s/##HOLD##/,/g'
这将匹配引号中的文本并为逗号添加占位符,然后将所有其他逗号切换为管道并将占位符放回逗号。您可以将## HOLD ##文本更改为您想要的任何内容。