我在 Ruby 中得到了正则表达式。
首先,问题本身并不相同。 这不是一个相同的问题,因为答案是不同的。 而且评论中的讨论也有所不同。
在第一个结果中,匹配整个.*
后,看起来'hello'
匹配没有。
但是为什么会发生呢?
[53] pry(main)> "hello".gsub(/.*/, "abc")
=> "abcabc"
[54] pry(main)> "hello".gsub(/^.*$/, "abc")
=> "abc"
答案 0 :(得分:4)
重要的一点是,regexp在同一位置永远不能匹配两次。比赛也不能重叠。此外,请注意,"hello"
中涉及六个可能的位置:一个在每个字符的开头,一个在末尾(请参见fenceposting)。
当您开始搜索/.*/
时,位置0处存在一个匹配项,并且该匹配项占用五个字符。这会使排名0、1、2、3和4的比赛失去资格(因为它们是第一场比赛的一部分)。
第二个匹配项从位置5开始匹配,并找到“ 0个或更多字符”(即0个字符)的匹配项。排名5不在第一场比赛中,因此也没有被“不重叠”规则取消资格。
当您以/^.*/
定位起点时,位置5不符合条件,因为它不是起点。
当您用/.*$/
定位末尾时,位置0和位置5都会检测到它们的5个字符或0个字符匹配之后,它们分别位于搜索字符串的末尾,因此您仍然可以都匹配。
当您使用/.+/
将正则表达式更改为“ 1个或更多字符”时,位置5再次不符合条件,因为没有更多的字符可匹配,但至少需要1个字符。
还请注意,不仅仅是Ruby,在我测试的所有引擎中都发现了相同的行为。 Python的sub
有点不一致(可能是因为其邻接条件?不确定),但是findall
报告了两个相同的匹配项:
re.findall('.*', 'hello') # => ['hello', '']
JavaScript的工作方式类似于Ruby:
"hello".replace(/.*/g, "abc") // => "abcabc"
Java也是如此:
"hello".replaceAll(".*", "abc") // => "abcabc"
甚至是PHP(使用PREG):
preg_replace('/.*/', 'abc', 'hello'); # => "abcabc"
答案 1 :(得分:1)
这是因为正则表达式引擎不会返回,这意味着当它与某些文本匹配时,它将永远不会在匹配的文本内返回,也就是说,matvhes不会重叠。
您使用了*
量词,表示它是贪婪的,因此将尽可能匹配。如果您使用*?
,那么您将在字符串的每个位置获得匹配,因为?
使它变得非贪婪,因此它将至少匹配。 *
表示零个或多个字符,但您将获得0个长度的匹配项。