我是SED的新手,有一个简单的问题。我以前用它来替换和删除字符,但这有点不同。我需要消除引号中的逗号,然后删除csv文件中的引用。所以这个:
"5,196,386","99,017",493,21
应该看起来像这样:
5196386,99017,493,21
答案 0 :(得分:1)
gnu awk one-liner:
awk -v FPAT='([^,]+|"[^"]+")' -v OFS="," '{for(i=1;i<=NF;i++)gsub(/[",]/,"",$i)}7'
以你的例子:
kent$ awk -v FPAT='([^,]+|"[^"]+")' -v OFS="," '{for(i=1;i<=NF;i++)gsub(/[",]/,"",$i)}7' <<< '"5,196,386","99,017",493,21'
5196386,99017,493,21
答案 1 :(得分:0)
您需要使用多个s///
操作执行此操作。当引号之间只有逗号和数字时,第一个将消除引号对之间的逗号;第二个将消除引号(现在它们之间只有数字):
sed -e 's/"\([0-9][0-9]*\),\([0-9,][0-9,]*\)"/"\1\2"/g' \
-e 's/"\([0-9][0-9]*\),\([0-9,][0-9,]*\)"/"\1\2"/g' \
-e 's/"\([0-9][0-9]*\)"/\1/g'
您必须经常重复第一个操作,因为引号之间可以出现最大逗号数。如果您的价值达到数十亿美元,则需要第三份副本。
答案 2 :(得分:0)
我会使用带有正确CSV解析器的语言。例如:
echo '"5,196,386","99,017",493,21' |
ruby -rcsv -ne 'CSV.parse($_) do |row|
puts CSV.generate_line(row.map {|e| e.delete(",")})
end'
5196386,99017,493,21
答案 3 :(得分:0)
这几乎适用于所有awk
echo '"5,196,386","99,017",493,21' | awk 'BEGIN {FS=OFS=""} {for (i=1;i<=NF;i++) {if ($i=="\"") {f=!f;$i=""}; if (f && $i==",") $i=""}}1'
5196386,99017,493,21
它是如何运作的:
awk '
BEGIN { # Begin block
FS=OFS=""} # Set input and output Field separator to "" (nothing) makes loop work on every characters
{for (i=1;i<=NF;i++) { # Looping trough line, one and one character at the time
if ($i=="\"") { # If a double quote is found do:
f=!f # Swap the flag "f" (If "f" is true, you are inside a double quote string
$i=""} # Delete the double quote
if (f && $i==",") # If "f" is true and we find a comma "," (inside a double quote string):
$i=""} # Delete the comma
}
1 # Print the line.
' file
答案 4 :(得分:0)
这可能适合你(GNU sed):
sed -r ':a;s/"[0-9,]+"/\n&\n/;T;h;s/[,"]//g;G;s/.*\n(.*)\n.*\n(.*)\n.*\n/\2\1/;ta' file
这会将\n
个标记放在双引号字段周围,复制整行,删除双引号和逗号,然后将该行重新组合在一起并重复直到不再需要更改为止。
另一种方法:
sed -r 's/^/\n/;ta;:a;s/\n+$//;t;s/\n\n"/\n/;ta;s/\n"/\n\n/;ta;s/\n\n,/\n\n/;ta;s/(\n+)(.)/\2\1/;ta' file
使用\n
作为标记,通过字符串逐个字符传递。当下一个字符在引用字段内时,有两个\n
标记。
答案 5 :(得分:0)
awk '{gsub(/"5,196,386","99,017"/,"5196386,99017")}1' file
5196386,99017,493,21