1

The following works in Ruby for commafication (adding , to a number, so 12345 becomes 12,345)

def r(s)
  s.gsub(/(?<=\d)(?=(\d\d\d)+\b)/, ",")
end

s = ""
1.upto(20) do |i|
  s += (i % 10).to_s
  puts r(s)
end

But I wonder why the variations r2 and r3 won't work?

def r2(s)
  s.gsub(/(?<=\d)(?=(\d\d\d)+)\b/, ",")
end

def r3(s)
  s.gsub(/(?<=\d)(?=\d\d\d)+\b/, ",")
end

Nothing is modified at all, and I would think that 1234 does match (?<=\d)(?=(\d\d\d)+)\b so it is a bit strange. (I tried it using Perl as well, so it is not peculiar to Ruby).

Update: The following is the output for r, while for r2 and r3, no , is added at all:

1
12
123
1,234
12,345
123,456
1,234,567
12,345,678
123,456,789
1,234,567,890
12,345,678,901
123,456,789,012
1,234,567,890,123
12,345,678,901,234
123,456,789,012,345
1,234,567,890,123,456
12,345,678,901,234,567
123,456,789,012,345,678
1,234,567,890,123,456,789
12,345,678,901,234,567,890
4

3 回答 3

5

好吧,在 r2 中,您的前瞻是说接下来的三个字符必须是数字,但是您立即尝试匹配单词边界。它们是相互排斥的。

在 r3 中,您正在重复前瞻一次或多次,但是,作为前瞻,这是无稽之谈。您一遍又一遍地重复“接下来的三个字符必须是数字”,但它们要么会是,要么不会。说不止一次是无稽之谈。而且您仍然有单词边界的问题。

前瞻就像堆栈上的 peek 函数。它不会向前移动指针,因为它不消耗任何东西。它匹配一个位置(将其视为字符之间的空格)。所以你的前瞻匹配三个数字后面的位置。但是接下来的语句 (the \b) 匹配左侧字符是单词字符(通常[a-zA-Z0-9_]或类似的字符)而右侧字符不是(空格、句点等)的位置,反之亦然。由于先前的向后查找要求该位置之前有数字,而向前查找需要一系列数字,因此在定义的位置处不可能有单词边界。

例子

以下正则表达式将始终失败:

^(?=\d\d\d)\d\d\b

表示匹配必须从输入的^开头开始。前瞻断言接下来的三个字符必须是数字(但不消耗它们)。下面的表达式表示接下来的两个字符必须是数字(并消耗它们,将指针向前移动),然后是非数字(单词边界)。但这违反了要求接下来的三个字符必须是数字的前瞻。因此,匹配失败。

见:http ://www.regular-expressions.info/lookaround.html

于 2012-10-26T14:10:57.697 回答
1

r2 用单词表示的是“匹配一个单词边界,它后面有多个数字,可以被 3 整除,并且前面有一个数字”。这是一个矛盾,因为没有边界可以在它之前和之后有数字。它不会是一个边界。因此,这个表达式没有什么可以匹配的。

于 2012-10-26T14:15:04.417 回答
0

r2并且在前瞻之后直接r3单词边界,而不是在里面。\b这永远不会匹配,因为您还希望它前面有一个数字 - 它肯定在一个单词中。

顺便说一句,我认为+前瞻之后是无效的。如果前瞻匹配,它当然会重复匹配。如果要重复 3 位数字,则必须在前瞻内。

于 2012-10-26T14:11:42.950 回答