如何使正则表达式从字符串开头开始匹配

4

我遇到了一个奇怪的问题(可能以前见过但从未关注过)。

以下是代码要点:

my $url = 'http://twitter.com/' . $handle;
my $page = get($url);

if($page =~ m/Web<\/span>\s*<a href=\"(.+?)\"/gi) {
    $website = $1;
}

if($page =~ m/follower_count\" class=\"stats_count numeric\">(.+?)\s*</g) {
    $num_followers = $1;
}

它获取Twitter网址并进行一些正则表达式以捕获用户的关注者数量和网站。此代码实际上可以正常工作。但是,当您切换顺序并在搜索关注者之后搜索网站时,网站将为空。事实证明,当您对字符串进行正则表达式时,它似乎会保存最后匹配位置的位置。在HTML中,关注者数显示在网站显示之后。如果您首先执行关注者计数正则表达式,则就像它重新启动了网站正则表达式,其中关注者计数停止(就像字符串的索引引用)。让我感到困惑的是,我在末尾有"g"运算符,表示“全局”,即“从开头全局搜索字符串”。我错过了什么吗?我似乎无法弄清楚为什么它会恢复字符串上的最后一个正则表达式位置(如果这有意义)。

1
请提供一下你应用正则表达式的两个文本行的例子。 - DaveC
这个问题已经有答案了,但是需要澄清两点:1- 在 s/something/somethingelse/g 中使用 "g" 是必要的,以替换所有出现的内容,对吗?2- 我在上面的示例代码中使用的 "m" 运算符是不必要的。 - Jeff
  1. 是的,s///g 进行全局替换,而 s/// 只进行单个替换。
  2. 是的。只有当你使用不同的括号时才需要 mm(pattern)m[pattern] 或类似的情况。
- Philip Potter
4个回答

13

在标量上下文中,/g修饰符并不像你想的那样起作用。请将其删除。

正如perlretut所解释的那样,在标量上下文中,/g会循环遍历每个匹配项。它是为循环使用而设计的,例如:

while ($str =~ /pattern/g) {
    # match on each occurence of 'pattern' in $str in turn
}

使用/g的另一种方法是在列表上下文中使用:

my @results = $str =~ /pattern/g; # collect each occurence of 'pattern' within $str into @results

如果你在标量上下文中使用/g,并且不进行迭代,那么你几乎肯定没有正确地使用它。


2
啊!我知道我在很多次使用它(特别是在while循环中,就像你描述的那样),但我忘记了它的含义!现在这有意义了。非常感谢! - Jeff

5

引用 Regexp Quote Like Operators 中的话:

在标量上下文中,每次执行 m//g 都会查找下一个匹配项,如果匹配则返回 true,否则返回 false。最后一次匹配后的位置可以使用 pos() 函数读取或设置;参见 pos。失败的匹配通常会将搜索位置重置为字符串的开头,但您可以通过添加 /c 修饰符(例如 m//gc)来避免这种情况。修改目标字符串也会重置搜索位置。

因此,在标量上下文中(您正在使用的上下文),/g 不意味着“从开头开始搜索”,而是意味着“从字符串的 pos 开始搜索”。默认情况下(没有 /g),它会从开头开始搜索。

/g通常用于在字符串中查找正则表达式的所有匹配项,而不仅仅是第一个匹配项。在列表上下文中,它通过返回所有匹配项的列表来实现。在标量上下文中,它通过从前一次搜索结束的地方开始搜索(通常在循环中完成)来实现。


3
它的要点在于使用 /g 进行匹配时会保存上一次匹配的位置,以便下一次匹配从那里开始。在标量上下文中,通常会在 while 循环中执行多个连续匹配;在列表上下文中,/g 返回所有匹配结果(但不重叠)。您可以在 perlretut 的 Global Matching 和 perlop 的 Regexp-Quote-Like-Operators 中了解更多信息。
您可以使用 pos 函数查看当前位置。您还可以将 pos 用作左值来设置位置:pos($string) = 0; 将把位置重置为字符串的开头。
在循环之外的标量上下文中使用 /g 没有太多意义,因为您可以使用 \G 断言获得完全相同的功能。
当然,这样做没有人记得如何使用 \G,所以又回到了起点,但这是另一个话题。

0

1
这里不需要使用 pos/g 标志根本不需要使用。 - friedo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接