代码之家  ›  专栏  ›  技术社区  ›  Carson Myers

为什么这个perl regex不能工作?

  •  2
  • Carson Myers  · 技术社区  · 16 年前

    我有一个Perl脚本,它应该与这个字符串匹配:

    Sometimes, he says "hey fred, what's up?"

    它说如果它在单词的开头、结尾或中间找到了fred,或者它只是找到了“fred”。所以它匹配阿尔弗雷德和弗雷德里克。

    好吧,在这个字符串中,它应该说它自己找到了弗雷德,但它说它是在一个词的开头找到的。这是单词fred开头的regex,(它位于if-elsif阶梯中,从单词的开头、结尾到单词的中间):

    if(/.*\s+[fF][rR][eE][dD][^ \t\r\n,.:;'"].*/){
        print "found fred at beginning of a word:\n    $_\n";
    

    我用过 [^ \t\r\n,.:;'"] 而不是 \S 如果单词后面跟着一些标点符号。显然,它不是一个完整的标点列表,但是对于这个例子来说,它并不重要,因为它后面跟着一个逗号。

    这是一个foreach循环…如果这意味着什么,这是练习7-1 Perl语言入门 第五版。

    更新

    书中的练习是编写一个Perl程序,在单词列表中查找“fred”。然后它问,剧本是在“弗雷德里克”还是“阿尔弗雷德”中找到弗雷德的?然后它说写一个文本文件,谈论弗雷德·弗林斯通和他的朋友,并把它作为脚本的输入。

    我想出来了,有点: 在写我忘记的问题的时候,我一定改变了一些东西:我再次测试它,而不是匹配单词的开头,它只是说它在任何地方都找到了它。所以问题不在于它认为它是一个单词的开头,而是它认为它不是单词中唯一的东西。我添加了 [,.:;'"]?\s+ 与整个单词“fred”匹配的代码,它起作用。我想在问之前我应该多考虑一下。

    3 回复  |  直到 16 年前
        1
  •  1
  •   Massa    16 年前

    如果你想匹配 Fred frederick 但不是 Alfred ,那么您的regex是:

    /\bfred\w*\b/i
    

    也就是说:单词边界后接(大小写插入式)“fred”,后接零个或多个单词字符,后接另一个单词边界。如果你只是想 弗雷德里克 但平原 弗莱德 然后出来:

    /\bfred\w+\b/i
    

    即单词边界,“fred”,一个或多个单词字符,单词边界。

    更新:重新阅读您的问题,似乎您需要:

    perl -E '
    use strict;
    use warnings;
    for( "nobody is here",
        "I am Frederick Flintsone",
        "she is alfredine",
        "I am Alfred Hitchcock",
        "fred has left the building" ) {
      say;
      if( ! /\b(\w*)fred(\w*)\b/i ) {
        say "no fred!"
      } elsif( ! length "$1$2" ) {
        say "fred by itself!"
      } elsif( ! length $2 ) {
        say "something-fred!"
      } elsif( ! length $1 ) {
        say "fred-something!"
      } else {
        say "something-fred-something!"
      }
    }'
    

    输出:

    nobody is here
    no fred!
    I am Frederick Flintsone
    fred-something!
    she is alfredine
    something-fred-something!
    I am Alfred Hitchcock
    something-fred!
    fred has left the building
    fred by itself!
    
        2
  •  9
  •   Don Jones    16 年前

    您可以将\b用于单词边界,将\w用于单词字符,而且,大小写不敏感的/i修饰符比使用[ff]等更干净。

    类似:

    if ($st =~ m{\b fred \w+ }xi) {
        print "Found fred at the beginning of a word";
    } else {
        print "Not found";
    }
    

    如果您需要将“fred”作为一个词本身查找,则使用 \b fred \b .

    我建议你读一下 http://perldoc.perl.org/perlre.html

        3
  •  2
  •   Cebjyre    16 年前

    你确定它不起作用吗?对于您的示例案例,它看起来很好,我刚刚运行的代码的一个稍微调整过的版本给出了预期的答案:

    #!/usr/bin/perl
    
    use strict; use warnings;
    
    my $st = q{Sometimes, he says "hey fred, what's up?"};
    
    foreach($st)
    {
        if(/.*\s+[fF][rR][eE][dD][^ \t\r\n,.:;'"].*/){
            print "found fred at beginning of a word:\n    $_\n";
        }
        else
        {
            print "not found in $_";
        }
    }
    

    正在报告“未找到”部分(如预期的那样,因为我没有执行“仅Fred”检查)。