对一个字符串按每x位进行分割

1
2
# 每8位进行分割,表达式所匹配的含义是:匹配一个位置,左边有字符,右边包含的字符总数是8的倍数
(?<=\w)(?=(\w{8})+\b)

使用 perl 来进行替换

1
2
3
# 配置位置,并不匹配一个具体的字符,锚点
echo 12345678 | perl -p -n -e 's/(?<=\d)(?=(\d{3})+$)/,/g' # 表达式的 $ 是必须的,匹配文本的结束位置
12,345,678

使用 sed 进行替换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 使用捕获型括号
# :start 定义标签,执行替换命令
# t 表示 test,如果替换命令成功执行,则跳转至对应的标签执行,否则结束
$ echo 12345678 | sed '{
:start
s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/ # {} () 需要使用 \ 进行转移表达其特殊含义,这点和一般使用的表达式引擎是有区别的
t start
}'
12,345,678

# 需要理解的一点是,匹配替换是一个循环的过程,直到测试至文本的末尾 (.*[0-9]) 一开始会匹配 '12345678', .* 匹配 '1234567', [0-9] 匹配 '8', 发现后面还需要匹配 3 个数字,于是进行回溯(面包屑),发现 (.*[0-9]) 匹配 '12345' 时,后面刚好有 3 个数字,能够匹配,所以本次匹配成功,所以第一次替换后的结果为 '12345,678'; 第二次替换后的结果为 '12,345,678'


# 使用 s 命令的 p 进行验证 (-n 关闭了默认的打印)
$ echo 12345678 | sed -n '{
:start
s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/p
t start
}'
12345,678
12,345,678