仅用 sed 或 awk 替换双引号之间的字符

仅用 sed 或 awk 替换双引号之间的字符

我在 CSV 文件中有这样的场景:

ID,PRICE,QUANTITY,ARRIVAL
01299,"41,5",1,0
26528,"412,03",0,0
38080,"2,35",0,0
38081,"2,35",0,0
..
..

我问自己的问题是:如何替换,,.但仅在价格中,用双引号括起来"...",在PRICE列中?

我尝试过

sed -i 's/\(,\)[^ ]*\( .*\)/\1"."\2/'

但没有成功,你能给我一个提示吗?

答案1

我建议使用 sed 的“-E”选项来扩展正则表达式。如果引号之间只有数字,您可以执行以下操作:

~ $ cat foo
lorem, ipsum
"5,25", foobar
"foo,bar", foobar
~ $ cat foo | sed -E 's/"([0-9]+)\,([0-9]+)"/"\1.\2"/g'
lorem, ipsum
"5.25", foobar
"foo,bar", foobar

如果引号中包含大写和小写字母,则可以像这样扩展正则表达式:

~ $ cat foo | sed -E 's/"([0-9]+|[a-z]+|[A-Z]+)\,([0-9]+|[a-z]+|[A-Z]+)"/"\1.\2"/g'
lorem, ipsum
"5.25", foobar
"foo.bar", foobar

您可以在 regex101.com 轻松测试您的正则表达式:另请参阅:https://regex101.com/r/mlfSMp/1

答案2

使用csvformat来自csvkit

$ csvformat -D ';' file | tr , . | csvformat -d ';'
ID,PRICE,QUANTITY,ARRIVAL
01299,41.5,1,0
26528,412.03,0,0
38080,2.35,0,0
38081,2.35,0,0

上述命令将 CSV 分隔符从默认逗号更改为分号。然后,它将所有剩余的逗号更改为点,然后将字段分隔符更改回逗号。

或者,使用以下命令将 CSV 转换为 JSONcsvjson并修改数据jq

$ csvjson -I file | jq -r '(.[0] | keys_unsorted | @csv), (map(.PRICE |= sub(",";".") | [.[]] | @csv)[])'
"ID","PRICE","QUANTITY","ARRIVAL"
"01299","41.5","1","0"
"26528","412.03","0","0"
"38080","2.35","0","0"
"38081","2.35","0","0"

csvformat如果您想删除任何不需要的引号,请传递此参数(不带参数)。

jq表达式首先通过从输入数组中的第一个对象获取键来输出标头。然后,它修改PRICE每个元素的字段(将逗号更改为点)并将值格式化为 CSV 以便输出。

第二个变体和第一个变体之间的效果差异在于我们只影响列PRICE。任何其他字段中的任何嵌入逗号都将保持不变。


作为参考,考虑到问题中的 CSV 数据,从 获取的JSON 文档jq为输入csvjson

[
  {"ID":"01299","PRICE":"41,5","QUANTITY":"1","ARRIVAL":"0"},
  {"ID":"26528","PRICE":"412,03","QUANTITY":"0","ARRIVAL":"0"},
  {"ID":"38080","PRICE":"2,35","QUANTITY":"0","ARRIVAL":"0"},
  {"ID":"38081","PRICE":"2,35","QUANTITY":"0","ARRIVAL":"0"}
]

答案3

调整这个回答仅删除逗号分隔文件中引号之间的逗号解决方案awk

awk -F'"' -v OFS='"' '{ for (i=2; i<=NF; i+=2) gsub(",", ".", $i) } 1' infile

哪里infile

ID,PRICE,QUANTITY,ARRIVAL
01299,"41,5",1,0
26528,"412,03",0,0
38080,"2,35",0,0
38081,"2,35",0,0

结果是

ID,PRICE,QUANTITY,ARRIVAL
01299,"41.5",1,0
26528,"412.03",0,0
38080,"2.35",0,0
38081,"2.35",0,0

代码的解释与引用的答案相同,因此我不再重复,除了:

  • 输出字段分隔符现在是"(即OFS='"'),而不是空(即OFS=''),并且;
  • nowgsub将逗号 ( ",") 替换为句点 ( "."),而不是空 ( "")

相关内容