我正在尝试对通用格式的行执行以下替换:
BBBBBBB.2018_08,XXXXXXXXXXXXX,01/01/2014,"109,07",DF,CCCCCCCCCCC, .......
如您所见,问题是它是一个逗号分隔的文件,其中的特定字段包含逗号十进制。我想用一个点代替它。
我尝试过这种方法,以替换比赛后第一次出现的模式,但无济于事,有人可以帮助我吗?
sed -e '/,"/!b' -e "s/,/./"
sed -e '/"/!b' -e ':a' -e "s/,/\./"
先谢谢了。 awk或perl解决方案也会对我有帮助。这很费力:
gawk -F "," 'substr($10, 0, 3)==3 && length($10)==12 { gsub(/,/,".", $10); print}'
这会产生相同的文件。
答案 0 :(得分:3)
CSV文件应使用适当的awk
变量在FPAT
中进行解析,该变量定义在此文件中构成有效 field 的内容。完成此操作后,您只需遍历各个字段即可进行所需的替换
gawk 'BEGIN { FPAT = "([^,]+)|(\"[^\"]+\")"; OFS="," }
{ for(i=1; i<=NF;i++) if ($i ~ /[,]/) gsub(/[,]/,".",$i);}1' file
请参见this answer of mine,以了解如何使用FPAT
变量定义和解析CSV文件内容。另请参见Save modifications in place with awk进行sed -i''
之类的就地文件修改。
答案 1 :(得分:1)
以下sed
将转换带引号的数字字段中的所有十进制分隔符:
sed 's/"\([-+]\?[0-9]*\)[,]\?\([0-9]\+\([eE][-+]\?[0-9]+\)\?\)"/"\1.\2"/g'
答案 2 :(得分:1)
这可能对您有用(GNU sed):
sed -E ':a;s/^([^"]*("[^",]*"[^"]*)*"[^",]*),/\1./;ta' file
此正则表达式在一对,
中匹配一个"
,并用.
代替。正则表达式锚定到行的开头,因此需要重复进行,直到无法再匹配其他匹配为止,因此:a
和ta
命令会导致替换被迭代,同时进行任何替换成功。
该解决方案期望所有双引号都匹配并且没有双引号,即\"
不在一行中。
答案 3 :(得分:1)
如果您的输入始终遵循仅一个带引号的字段(包含1个逗号)的格式,那么您所需要的就是:
$ sed 's/\([^"]*"[^"]*\),/\1./' file
BBBBBBB.2018_08,XXXXXXXXXXXXX,01/01/2014,"109.07",DF,CCCCCCCCCCC, .......
如果比这更复杂,请参见What's the most robust way to efficiently parse CSV using awk?。
答案 4 :(得分:0)
假设您有:
BBBBBBB.2018_08,XXXXXXXXXXXXX,01/01/2014,"109,07",DF,CCCCCCCCCCC
尝试一下:
awk -F',' '{print $1,$2,$3,$4"."$5,$6,$7}' filename | awk '$1=$1' FS=" " OFS=","
输出将是:
BBBBBBB.2018_08,XXXXXXXXXXXXX,01/01/2014,"109.07",DF,CCCCCCCCCCC
您只需要知道字段号即可替换它们之间的字段分隔符。
答案 5 :(得分:0)
要像在perl中一样使用regexp,必须使用-r
激活扩展的正则表达式。
因此,如果您要替换所有数字并省略“”符号,则可以使用以下代码:
echo 'BBBBBBB.2018_08,XXXXXXXXXXXXX,01/01/2014,"109,07",DF,CCCCCCCCCCC, .......'|sed -r 's/\"([0-9]+)\,([0-9]+)\"/\1\.\2/g'
如果您只想替换首次出现的内容,则可以使用:
echo 'BBBBBBB.2018_08,XXXXXXXXXXXXX,01/01/2014,"109,07",DF,CCCCCCCCCCC, .......'|sed -r 's/\"([0-9]+)\,([0-9]+)\"/\1\.\2/1'