【问题标题】:Want to use Bash & Regex to replace comma in file想使用 Bash & Regex 替换文件中的逗号
【发布时间】:2021-04-12 14:41:04
【问题描述】:

我需要替换 csv 文件中的特定字符,例如逗号。

我的文件包含用“;”分隔的文本和数字(csv 为法语...)

例子:

value;x;y;comment;
abc;123,45;987,65;abc;
abc;123.45;987.65;abc;
abc;123,45;987,65;abc, blabla;

小数点分隔符 ',' 和 '.' 混合使用被使用了。

我想将 ',' 替换为 '.'但仅适用于十进制值,不适用于 cmets 之类的文本。

我用正则表达式尝试了 sed

sed -i '/;[0-9]\+,[0-9]\+;/s/,/./g' file.csv

但是那替换所有逗号。我找不到如何只替换我想要的。

我只想在 bash 中这样做。

【问题讨论】:

  • 使用适当的 CSV 解析器会更简单,在许多其他语言的标准库中都可以使用。您还应该将替换限制为已知包含数字数据的字段,而不是所有字段。如果您没有合适的 CSV 解析器,至少使用 awk,它可以比 sed 更轻松地处理单个字段。
  • 为什么要专门使用正则表达式?如果您使用像 sed 这样的工具,那不再是“仅 bash”,因为 /bin/sed 是一个完全独立的可执行文件。 bash 具有内置的字符串操作工具,您不需要外部命令;这些通常基于 fnmatch 样式匹配而不是正则表达式,但这并不意味着它们不适合用例。

标签: regex linux bash csv replace


【解决方案1】:

一个使用扩展正则表达式和捕获组的sed 想法:

sed -E 's/([0-9]),([0-9])/\1.\2/g' file.csv

地点:

  • -E - 启用扩展的正则表达式支持
  • ([0-9]),([0-9]) - 匹配单个数字 + , + 单个数字
  • ([0-9]) - 定义一个捕获组(在这种情况下有 2 个捕获组)
  • \1.\2 - 打印捕获组#1 + . + 捕获组#2

这会生成:

value;x;y;comment;
abc;123.45;987.65;abc;
abc;123.45;987.65;abc;
abc;123.45;987.65;abc, blabla;

注意事项

  • 一旦 OP 得到满足,代码就会执行所需的操作,可以添加 -i 标志以使 sed 执行文件的就地更新
  • 这将错误地替换 ;3,2,4 five 6,7 eight ; 等字符串中的逗号(可以解决此问题,但需要更复杂的正则表达式)

【讨论】:

    【解决方案2】:

    你可以用这个更简单的sed:

    sed -i.bak -E 's/([0-9]),([0-9])/\1.\2/g' file
    
    value;x;y;comment;
    abc;123.45;987.65;abc;
    abc;123.45;987.65;abc;
    abc;123.45;987.65;abc, blabla;
    

    详情:

    • ([0-9]),([0-9]):匹配一个数字,后跟逗号,后跟一个数字。在捕获组#1 和#2 中捕获数字之前和之后
    • \1.\2:替换为反向引用#1,后跟点,后跟反向引用#2

    或者,您可以使用这个更强大的awk 解决方案:

    awk 'BEGIN {FS=OFS=";"} {for (i=1; i<=NF; ++i) 
    if ($i ~ /^[0-9]+,[0-9]+$/) sub(/,/, ".", $i)} 1' file
    
    value;x;y;comment;
    abc;123.45;987.65;abc;
    abc;123.45;987.65;abc;
    abc;123.45;987.65;abc, blabla;
    

    【讨论】:

      【解决方案3】:

      你可以试试:

      sed -i 's/;\([0-9]\+\),\([0-9]\+\)/;\1.\2/g' file.csv
      

      注意:如果您使用-i 选项,请不要忘记备份您的原始数据,以防万一。

      【讨论】:

      • -i[SUFFIX], --in-place[=SUFFIX] 就地编辑文件(如果提供了 SUFFIX,则进行备份)
      猜你喜欢
      • 2011-09-14
      • 2011-02-26
      • 1970-01-01
      • 2018-05-14
      • 2011-06-18
      • 1970-01-01
      • 1970-01-01
      • 2023-02-17
      相关资源
      最近更新 更多