用逗号分隔的行进行sed模式否定
我有一个充满行的文本文件,看起来像:用逗号分隔的行进行sed模式否定,sed,Sed,我有一个充满行的文本文件,看起来像: Female,"$0 to $25,000",Arlington Heights,0,60462,ZD111326,9/18/13 0:21,Disk Drive 我正在尝试将所有逗号,更改为管道|,引号中的逗号除外。 尝试使用sed(我是新手)。。。而且它不起作用。使用: sed '/".*"/!s/\,/|/g' textfile.csv 有什么想法吗?使用awk可以: kent$ cat f foo,foo,"x,y,z",foo,"a,b,c"
Female,"$0 to $25,000",Arlington Heights,0,60462,ZD111326,9/18/13 0:21,Disk Drive
我正在尝试将所有逗号,
更改为管道|
,引号中的逗号除外。
尝试使用sed(我是新手)。。。而且它不起作用。使用:
sed '/".*"/!s/\,/|/g' textfile.csv
有什么想法吗?使用awk可以:
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
kent$f类
foo,foo,“x,y,z”,foo,“a,b,c”,foo,“是,不是”
女性,“0至25000美元”,阿灵顿高地,060462,ZD111326,9/18/13 0:21,磁盘驱动器
肯特$ AWK-F′- v OFS='' { for(i=1;i作为测试实例),考虑此文件:
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
)
[^”]*
这将查找零个或多个非引号字符
(“[^”]*“[^”]*)*
在括号外的*
表示我们在括号内寻找零个或多个模式。括号内的模式由引号、任意数量的非引号、引号和非引号上的任意数字组成
换句话说,此分组仅匹配引号对。由于括号外的*
,它可以匹配任意偶数个引号
)
这将关闭主分组
,
这要求分组后面必须跟一个逗号
ta
如果先前的s
命令成功进行了替换,则test
命令将告诉sed
跳回标签a
,然后重试
如果没有替换,那么我们就完了
我建议使用带有适当CSV解析器的语言。例如:
ruby -rcsv -ne 'puts CSV.generate_line(CSV.parse_line($_), :col_sep=>"|")' file
在这里,我会使用gnu awks
FPAT
。它定义一个字段的外观,告诉您分隔符是什么。然后您可以将输出分隔符设置为|
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
awk-F'{for(i=1;i
这将匹配引号中的文本并为逗号放置一个占位符,然后将所有其他逗号切换为管道并将占位符重新放置为逗号。您可以将##HOLD##文本更改为您想要的任何文本。修订:我认为否定模式会导致跳过整行。这可能吗?您是正确的,sed正在运行所以当它找到你的正则表达式时,它会匹配这一行,当你否定它时,它会删除整行。还有,为什么是“7”在for循环结束时?@Sam用于获取打印输出。它可以是任何数字,如1
或8
。然后它将执行默认操作,print
做得好,我从来没有想过嵌套保留空间,我想sed就是用于此的..=)
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
sed 's/"\(.*\),\(.*\)"/"\1##HOLD##\2"/g;s/,/|/g;s/##HOLD##/,/g'