Replace SED条件替换
我是SED新手,有一个简单的问题。我以前用过它来替换和删除字符,但这有点不同。我需要消除引号中的逗号,然后消除csv文件中的引号。因此:Replace SED条件替换,replace,sed,conditional,Replace,Sed,Conditional,我是SED新手,有一个简单的问题。我以前用过它来替换和删除字符,但这有点不同。我需要消除引号中的逗号,然后消除csv文件中的引号。因此: "5,196,386","99,017",493,21 结果应该是这样的: 5196386,99017,493,21 您需要通过多个s///操作来完成此操作。第一种方法是在引号之间只有逗号和数字时,消除引号对之间的逗号;第二个将删除引号(现在引号之间只有数字): 必须尽可能多地重复第一个操作,直到引号之间可以出现的最大逗号数为止。如果您的价值达到数十亿,您
"5,196,386","99,017",493,21
结果应该是这样的:
5196386,99017,493,21
您需要通过多个
s///
操作来完成此操作。第一种方法是在引号之间只有逗号和数字时,消除引号对之间的逗号;第二个将删除引号(现在引号之间只有数字):
必须尽可能多地重复第一个操作,直到引号之间可以出现的最大逗号数为止。如果您的价值达到数十亿,您需要第三份副本。gnu awk one liner:
awk -v FPAT='([^,]+|"[^"]+")' -v OFS="," '{for(i=1;i<=NF;i++)gsub(/[",]/,"",$i)}7'
awk-v FPAT='([^,]+|“[^”]+”)-v OFS=“,”{for(i=1;i我会使用带有适当CSV解析器的语言。例如:
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
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'
这应该适用于几乎所有的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
echo'5196386',99017',493,21'|awk'BEGIN{FS=OFS=“”}{for(i=1;i这可能适用于您(GNU-sed):
这将在双引号字段周围放置\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
的标记。能否将[0-9][0-9]*
简化为[0-9]+
或甚至\d+
..?这取决于您使用的是sed
的哪个亚物种。我使用的符号将适用于任何符合POSIX的sed
;您提出的扩展可用于sed
的其他变体。我没有意识到+
是-感谢您的澄清这让我很惊讶,你是这样写的,这就是我问这个问题的原因。现在我明白了。+1-一旦文本操作变得更加复杂,第一个反射(或perl)就是使用awk
。thx@Floris,事实上大括号可以保存。(FPAT)请注意,FPAT
是GNUawk
的一项功能,不一定出现在其他版本的awk
中;POSIX没有指定它。@JonathanLeffler是的,我想我在回答的一开始就提到了这一点。
awk '{gsub(/"5,196,386","99,017"/,"5196386,99017")}1' file
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
sed -r ':a;s/"[0-9,]+"/\n&\n/;T;h;s/[,"]//g;G;s/.*\n(.*)\n.*\n(.*)\n.*\n/\2\1/;ta' file
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
awk '{gsub(/"5,196,386","99,017"/,"5196386,99017")}1' file
5196386,99017,493,21