【问题标题】:Opposite of (foo|bar|baz)(foo|bar|baz) 的对面
【发布时间】:2012-05-16 21:08:12
【问题描述】:

我想要一个正则表达式来匹配除更广泛表达式中的一些特定选项之外的所有内容。

以下示例将匹配 test_foo.pl 或 test_bar.pl 或 test_baz.pl:

/test_(foo|bar|baz)\.pl/

但我想要恰恰相反:

match test_.*\.pl except for where .* = (foo|bar|baz)

我对此的选择有限,因为这不是直接进入 perl 程序,而是cloc, a program that counts lines of code (that happens to be written in perl) 的一个参数。所以我正在寻找一个可以在一个正则表达式中完成的答案,而不是多个链接在一起。

【问题讨论】:

    标签: regex perl


    【解决方案1】:

    您应该能够通过使用负前瞻来完成此操作:

    /test_(?!foo|bar|baz).*\.pl/
    

    如果foobarbaz 紧跟在test_ 之后,这将失败。

    请注意,这仍然可以匹配 test_notfoo.pl 之类的内容,并且会在 test_fool.pl 上失败,如果您不希望这种行为,请通过添加一些确切应该和不应该匹配的示例来澄清。

    如果您想接受test_fool.pltest_bart.pl 之类的内容,则可以将其更改为以下内容:

    /test_(?!(foo|bar|baz)\.pl).*\.pl/
    

    【讨论】:

    • 我认为您的解决方案会拒绝test_bart.pl,但据我所知,OP 将接受test_bart.pl,但不接受test_bar.pl(仅作为示例,注意与bart 相关的特殊内容)
    • 要使 only 排除给定,您还需要匹配表达式的结尾:/test_(?!(foo|bar|baz)\.pl).*\.pl/。 (如果字符串包含多个文件名(由于.*),此版本也将不正确,但在问题的上下文中不应该是这种情况。)
    【解决方案2】:
    #!/usr/bin/env perl
    
    use strict; use warnings;
    
    my $pat = qr/\Atest_.+(?<!foo|bar|baz)[.]pl\z/;
    
    while (my $line = <DATA>) {
        chomp $line;
        printf "%s %s\n", $line, $line =~ $pat ? 'matches' : "doesn't match";
    }
    
    
    __DATA__
    test_bar.pl
    test_foo.pl
    test_baz.pl
    test baz.pl
    0test_bar.pl
    test_me.pl
    test_me_too.txt
    

    输出:

    test_bar.pl 不匹配
    test_foo.pl 不匹配
    test_baz.pl 不匹配
    测试 baz.pl 不匹配
    0test_bar.pl 不匹配
    test_me.pl 匹配
    test_me_too.txt 不匹配

    【讨论】:

      【解决方案3】:
      (?:(?!STR).)*
      

      STR
      

      作为

      [^CHAR]
      

      CHAR
      

      所以你想要

      if (/^test_(?:(?!foo|bar|baz).)*\.pl\z/s)
      

      更具可读性:

      my %bad = map { $_ => 1 } qw( foo bar baz );
      
      if (/^test_(.*)\.pl\z/s && !$bad{$1})
      

      【讨论】:

        【解决方案4】:

        嗯,我可能误解了你的问题。无论如何,也许这会有所帮助......


        你会否定匹配操作符。例如:

        perl -lwe "print for grep ! m/(lwp|archive).*\.pl/, glob q(*.pl)"
        # Note you'd use single-quotes on Linux but double-quotes on Windows.
        # Nothing to do with Perl, just different shells (bash vs cmd.exe).
        

        ! 否定匹配。以上是以下的简写:

        perl -lwe "print for grep ! ($_ =~ m/(lwp|archive).*\.pl/), glob q(*.pl)"
        

        也可以使用否定匹配运算符!~写成,如下:

        perl -lwe "print for grep $_ !~ m/(lwp|archive).*\.pl/, glob q(*.pl)"
        

        如果您想知道,glob 仅用于根据您的示例获取文件名的输入列表。我只是用另一种匹配模式替换了适合我在目录中方便使用的文件。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-03-04
          • 2012-04-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多