使用正则表达式匹配字符串中的3位组

时间:2018-01-15 11:08:44

标签: regex perl

这就是我想要做的事情:

  

给定一个字符串,12345678,commify(str)应该给我12,345,678。

使用Perl使用正则表达式解决问题,解决此问题的解决方案是:

  

S /(小于?= \ d)(?!=(\ d \ d \ d)+(\ d))/,/克

来源:掌握正则表达式

我在理解这个问题时遇到的问题是我们如何捕获此字符串的“345”部分。我能想到的一件事是正则表达式指针“我”(这是我可视化的方式)从1开始,另一个指针“j”遍历整个字符串并找到5到6之间的适当位置。然后我移动2.“j”再次遍历整个字符串,找到2和3之间的适当位置(因为现在已经在5和6之间插入了逗号)。 我的理解是否正确?如果没有,有人可以帮助我想象这个过程吗?

注意:我发现了类似的问题,但它们似乎没有解释问题是如何解决的,而是说出了确切的答案。

3 个答案:

答案 0 :(得分:4)

(?<=\d)(\d\d\d)+(?!\d)

如何运作,从右边阅读:

  • (?!\d) lookahead断言确保此点之后没有数字,光标(在输入中)就在最后一位之后
  • (\d\d\d)+匹配一个或多个三位数组
  • (?<=\d)确保在群组的第一个数字之前仍有一个数字

关于回溯的更新:参加123456789

只要在光标前找到一个数字,第一个引擎就会启动:1

之后
1.23456789

然后它尝试匹配至少1和三个数字组

1.234.567.89
在89之后它没有找到第三个数字,也因为负向前瞻而回溯它无法匹配,所以它在开始时回溯并转到下面的字符:2

12.345.678.9
再次,它无法在一组三个中找到第二个数字,因此它变为3

123.456.789

现在没有更多的数字,所以匹配。

请注意,最糟糕的情况是当numbre是3的倍数时,它就是每次替换所做的事情,因为前瞻不会向前移动输入光标。

包括perl one-liner

perl -pe 's/(?<=\d)(?=(\d{3}(?{print "matched $&.\n"}))+(?!\d(?{print "failed: $&.\n"})))/,/g'  <<<123456789

答案 1 :(得分:3)

将数千个分隔逗号添加到数字本身就是一种从右到左更容易做到的事情,因为人们会朝着这个方向发展。反转数的算法很简单:用三个数字后跟逗号替换每组三个数字。在下面的代码片段中,我使用了这个反向技巧,然后在最后再次反转修改后的数字。

$s = "12345678";
print $s . "\n";
$t = reverse $s;
$t =~ s/(\d{3})/${1},/g;
$s = reverse $t;
print $s;

12345678
12,345,678

Demo

答案 2 :(得分:2)

这是获取数据的简单方法

$num=12345678;
$num =~ s/(\d)(?=(\d{3})+(\D|$))/$1\,/g;
print $num;