使用SED进行条件替换

时间:2014-01-23 15:11:12

标签: replace sed conditional

我是SED的新手,有一个简单的问题。我以前用它来替换和删除字符,但这有点不同。我需要消除引号中的逗号,然后删除csv文件中的引用。所以这个:

"5,196,386","99,017",493,21

应该看起来像这样:

5196386,99017,493,21

6 个答案:

答案 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