【问题标题】:Is there a Perl equivalent of Python's re.findall/re.finditer (iterative regex results)?是否有 Python 的 re.findall/re.finditer(迭代正则表达式结果)的 Perl 等价物?
【发布时间】:2010-10-02 20:09:48
【问题描述】:

在 Python 中编译的正则表达式模式 have a findall method 执行以下操作:

返回所有不重叠的匹配项 字符串中的模式,作为列表 字符串。字符串被扫描 从左到右,匹配是 按找到的顺序返回。如果一个或 更多的群体出现在 模式,返回组列表;这 将是一个元组列表,如果 模式有多个组。空的 匹配项包含在结果中 除非他们触及 另一场比赛。

在 Perl 中执行此操作的规范方法是什么?我能想到的一个天真的算法是“当用空字符串搜索和替换成功时,做 [suite]”。我希望有更好的方法。 :-)

提前致谢!

【问题讨论】:

    标签: python regex perl iterator


    【解决方案1】:

    在您的比赛中使用/g 修饰符。来自perlop 手册:

    /g”修饰符指定全局模式匹配——即在字符串中匹配尽可能多的次数。它的行为方式取决于上下文。在列表上下文中,它返回与正则表达式中的任何捕获括号匹配的子字符串列表。如果没有括号,则返回所有匹配字符串的列表,就好像整个模式都有括号一样。

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

    【讨论】:

    • 天啊——当然!我应该从 Vim 领域意识到这一点。
    【解决方案2】:

    基于 Chris 的回复,将 //g 正则表达式封装在 while 循环中可能最相关,例如:

    my @matches;
    while ( 'foobarbaz' =~ m/([aeiou])/g )
    {
        push @matches, $1;
    }
    

    粘贴一些快速的 Python I/O:

    >>> import re
    >>> re.findall(r'([aeiou])([nrs])','I had a sandwich for lunch')
    [('a', 'n'), ('o', 'r'), ('u', 'n')]
    

    为了在 Perl 中获得类似的东西,构造可能是这样的:

    my $matches = [];
    while ( 'I had a sandwich for lunch' =~ m/([aeiou])([nrs])/g )
    {
        push @$matches, [$1,$2];
    }
    

    但一般来说,无论您要迭代什么函数,您都可以在 while 循环本身内完成。

    【讨论】:

    • 但是@matches = 'I had a sandwich for lunch' =~ m/([aeiou])([nrs])/g 呢?当然,您会得到一个扁平的阵列,但是您可以将其拼接成两个(在这种情况下)。 :-)
    • 啊-嗯。 Perl 的美妙之处在于总有另一种方式!我很高兴我说,“可能是这样的”:)
    【解决方案3】:

    不错的初学者参考,内容与@kyle的答案相似:Perl Tutorial: Using regular expressions

    【讨论】:

      猜你喜欢
      • 2012-06-19
      • 1970-01-01
      • 2017-09-07
      • 1970-01-01
      • 1970-01-01
      • 2021-09-30
      • 2015-10-28
      • 2020-03-26
      • 2022-01-13
      相关资源
      最近更新 更多