替换重叠的文本

Substituting text that overlaps

我有一段数据(data.txt),由于用户的错误,看起来像这样:

4,48
4485
4,49
4495
4,5
4505
4,51
 4,6
11445
11,45

模式是这样的:只要有逗号,0 就会被删除。所以:4450被不当改成了4,45,4600改成了4,6;和 11450 更改为 11,45.

因此,找到逗号时应执行两个操作:

  1. 在右边加一两个0,得到逗号右边的三位数字: d,dd -> d,dd0 ;或者 d,d -> d,d00
  2. 删除逗号 ddd0 ; dd00

最终结果应该是:

4480
4485
4490
4495
4500
4505
4510
4600
11445
11450

如何在 sed(或其他程序)上使用正则表达式来获得此结果?

  1. 一种解决方案是将数据拆分为两个文件,dataa.txt 和 datab.txt:

dataa.txt:

4,48
4485
4,49
4495
4,5
4505
4,51
 4,6
11445
11,45

和datab.txt:

4,5
4,6

第一个文件:

$ sed -E 's/(\,[0-9][0-9])//g;s/\,//g' dataa.txt

第二个文件:

$ sed -E 's/(\,[0-9])/0/g;s/\,//g' datab.txt 

然后,连接文件。如果没有这些额外的步骤(拆分和连接),这样做会更好。

  1. 使用awk有很好的解决方案(谢谢!),转载如下:

    $ awk '{gsub(/,/, ""); printf "%.4s\n", $0 * 1000}' data.txt

但是在处理 5 位数字时(您可以根据逗号左侧的位数找到它们)它也不起作用。它还需要拆分数据。

我们如何在不拆分数据的情况下获得最终结果?

(为清楚起见进行了编辑)

使用 GNU awk:

如果当前行包含 , 将其值乘以 1000。

LC_NUMERIC=de_DE.UTF-8 awk --use-lc-numeric '/,/{[=10=]=[=10=]*1000} {print}' file

或更短

LC_NUMERIC=de_DE.UTF-8 awk --use-lc-numeric '/,/{[=11=]*=1000}1' file

输出:

4480
4485
4490
4495
4500
4505
4510
4600

awk:

$ awk '{gsub(/,/, ""); printf "%.4s\n", [=10=] * 1000}' ip.txt
4480
4485
4490
4495
4500
4505
4510
4600
  • gsub(/,/, "") 删除所有逗号字符
  • [=13=] * 1000 将数字乘以 1000
  • printf "%.4s\n" 只打印前四位数字

首先确保逗号后有足够的数字。接下来删除第三个小数点后的所有内容并删除逗号:

sed -r 's/(,.*)/00/; s/,(...).*// ' data.txt

注意:00 记住与 </code> 匹配的字符串 1 并添加 <code>000.

$ awk 'split(,d,/,/)>1 { [=10=]=sprintf("%-*d",length(d[1])+3,d[1]d[2]); gsub(/ /,0) } 1' file
4480
4485
4490
4495
4500
4505
4510
4600
11445
11450

我可以使用正则表达式来解决:它缺少锚点“$”。 sed:

单行代码
sed -E 's/(\,[0-9]$)//g;s/(\,[0-9][0-9])//g;s/\,//g' data.txt

以前,我使用的是 \,[0-9],它与此数据不明确,并且匹配 4,54,51。正则表达式 \,[0-9]$ 仅匹配 4,5,而不匹配 4,55。要匹配 4,51 我们可以使用 \,[0-9][0-9].

感谢 awk 解决方案,非常优雅并且使用了不同的方法。