我在脚本中遇到了一段代码,它在每 3 个数字后面添加“,”。该代码仅考虑数字数据。
以下是代码。
sed 's/\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)/\1\2,\3/g' number.txt
号码.txt
1234
12345
123456
输出
1,234
12,345
123,456
1234,567
谁能解释一下代码流程..
答案1
sed(s特雷姆编辑itor)可以运行在s使用搜索和替换模式常用表达。存在一些特定于 sed 的转义,但对于正则表达式本身,您可以从以下位置授予解释工具正则表达式:
(
捕获组#1。将多个标记组合在一起并创建一个捕获组以提取子字符串或使用反向引用。
^
开始。匹配字符串的开头。
|
交替。其作用类似于布尔 OR。匹配 之前或之后的表达式|
。
[^
取反集。匹配不在集合中的任何字符。
0-9
范围。匹配“0”到“9”范围内的字符。区分大小写。
.
特点。匹配“.”特点。
]
)
(
捕获组#2。将多个标记组合在一起并创建一个捕获组以提取子字符串或使用反向引用。
[
字符集。匹配集合中的任何字符。
0-9
范围。匹配“0”到“9”范围内的字符。区分大小写。
]
+
量词。匹配 1 个或多个前面的标记。
)
(
捕获组#3。将多个标记组合在一起并创建一个捕获组以提取子字符串或使用反向引用。
[
字符集。匹配集合中的任何字符。
0-9
范围。匹配“0”到“9”范围内的字符。区分大小写。
]
{3}
量词。前面标记的匹配 3。
)
答案2
该模式捕获 (1) 行的开头或非数字或点的内容,后跟 (2) 任意数量的数字,至少一位,后跟 (3) 恰好三位数字。然后,它在 (2) 和 (3) 之间用逗号将它们放回原处,实际上添加了千位分隔符。第一组只需要避免接触小数点后的小数部分,因为我们不想1.2345
变成1.2,345
.
请注意,该模式是用基本正则表达式 (BRE) 编写的,需要在每个前面添加反斜杠()
并使{}
它们变得特殊。此外,还需要GNU sed,其中\+
和\|
在 BRE 中作为扩展也有特殊含义。该命令最好写为扩展正则表达式(sed -E
许多 sed 实现都支持):
sed -E 's/(^|[^0-9.])([0-9]+)([0-9]{3})/\1\2,\3/g'
此外,该模式仅进行一次替换,它不会向同一数字添加多个千个分隔符。最后的/g
会在同一行上匹配多次,但它不会处理已经替换的数据。1234567
会成为1234,567
,不会1,234,567
。为了解决这个问题,我们需要添加一个循环:
sed -E -e :a -e 's/(^|[^0-9.])([0-9]+)([0-9]{3})/\1\2,\3/g' -e ta
这里,:a
只是一个标签,最后的ta
t测试是否成功替换,并跳转回a
是否完成替换,实际上重复该过程的次数与执行某项操作的次数相同。因此1234567
将变成1,234,567
.
答案3
sed 's/foo/bar/g' number.txt
:这会读取文件number.txt
,并将正则表达式模式替换foo
为bar
.每行 ( ) 上的所有匹配都会发生这种情况/g
。\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)
:这是要替换的模式。转义括号中的每个部分\(…\)
都是一个“捕获组”。里面的图案被“捕获”以供以后使用。\(^\|[^0-9.]\)
:查找行的开头^
或\|
不是数字或句点的字符[^0-9.]
。这本质上是找到数字前面的字符。\([0-9]\+\)
:查找一个或多个数字[0-9]\+
。\([0-9]\{3\}\)
:找到 3 个数字[0-9]\{3\}
。
\1\2,\3
:用前两个捕获组替换上述匹配项,然后替换,
最后一个捕获组。换句话说,插入,
第二个和第三个模式之间。
因为sed
是“贪婪”的,所以它会尝试最大化匹配的长度。因此,最终的捕获组将是数字中的最后三个数字。
注意,许多“特殊”字符都用 转义\
,例如\(…\)
和\{3\}
。如果您sed
使用-E
or支持“扩展正则表达式” -r
,那么您不必转义这些。这将提高可读性。