【问题标题】:Perl Regular Expression to match special charactersPerl正则表达式匹配特殊字符
【发布时间】:2015-03-24 22:47:49
【问题描述】:

我在下面的代码中检查排除的数组中的特定变量位置。它适用于除一个以外的所有数组元素 (abc/def/libraries/linux_3.2.60-1+deb7u3.dsc) .当我提供这个元素作为我的位置时,它的打印“位置不排除”,即使它被排除在外。

我怎样才能让我的代码得到这个元素以及排除?

use strict;
use warnings;

my @excluded = (
 "xyz/efg/headers/",
 "abc/def/libraries/jni-mr.h",
 "abc/def/libraries/linux_3.2.60-1+deb7u3.dsc", 
);

my $location = "abc/def/libraries/linux_3.2.60-1+deb7u3.dsc";
my $badpath = 0;

foreach (@excluded) {
    # -- Check if location is contained in excluded array
    if ($location =~ /^$_/) {
       $badpath = 1;
       print "location is excluded : $location \n";
     }
   }

   if (! $badpath) {
      print "location is not excluded : $location \n";  
     }

期望的输出:

location is excluded : abc/def/libraries/linux_3.2.60-1+deb7u3.dsc

电流输出:

location is not excluded : abc/def/libraries/linux_3.2.60-1+deb7u3.dsc

【问题讨论】:

  • 如果您不打算应用任何正则表达式元字符,您最好使用index 函数。

标签: regex perl


【解决方案1】:

使用quotemeta($text)\Q$text\E(在双引号或正则表达式文字内)创建与$text 的值匹配的模式。换句话说,使用

if ($location =~ /^\Q$_\E/)

代替:

if ($location =~ /^$_/)

【讨论】:

    【解决方案2】:
    • 您似乎打算通过正则表达式定义排除项,但您没有在这些正则表达式中正确转义正则表达式元字符。对于您的失败案例,导致它失败的元字符是加号 (+),这是大多数正则表达式风格(包括 Perl)中的一个或多个乘数,但您需要逐字匹配。

    • 另外,我建议将 ^ 锚从循环移动到每个单独的正则表达式,这将使代码更加灵活,因为如果你愿意,你可以选择不锚定一些排除正则表达式.

    • 此外,您应该使用 qr() 构造,它允许您预编译正则表达式,从而节省 CPU。

    • 此外,此要求非常适合使用 grep()


    use strict;
    use warnings;
    
    my @excluded = (
        qr(^xyz/efg/headers/),
        qr(^abc/def/libraries/jni-mr\.h),
        qr(^abc/def/libraries/linux_3\.2\.60-1\+deb7u3\.dsc),
    );
    
    my $location = 'abc/def/libraries/linux_3.2.60-1+deb7u3.dsc';
    
    # -- Check if location is contained in excluded array
    my $badpath = scalar(grep($location =~ $_, @excluded )) >= 1 ? 1 : 0;
    if ($badpath) {
        print "location is excluded : $location \n";
    } else {
        print "location is not excluded : $location \n";
    }
    

    【讨论】:

    • 你不需要在那里使用scalar,因为表达式已经在标量上下文中。也不需要使用三元运算符。
    • @TLP,这是真的,但有两件事:(1)我通常喜欢明确说明标量与数组上下文。 Perl 上下文的区别给很多人带来了很多困惑,我什至认为这是该语言的一个有害特性,并且(2)我使用了三元运算符,因为 OP 将 0 和 1 存储在 $badpath ,所以我想做同样的事情(再次明确地)。
    • 在那里,我通过指定>= 1 测试将代码修改为更明确的更多,该测试阐明了三元运算符的 LHS 上发生的情况。很多 Perl 程序员似乎是反显式和亲crytic,所以他们会讨厌这一点,但搞砸了,清楚总比不清楚好。
    • 我不认为像你说的那样“明确”表述时实际上更清楚。如果有人不了解标量上下文,他们也不会理解 scalar 的用法。这不是一种透明的计数方式。而且您还将表达式堆叠在一行上。我会使用一个数组,例如my @count = grep ...; my $badpath = 0 # default; $badpath = 1 if @count >=1;
    • 好!我们同意使用scalar() 来获取数组的长度是神秘的。但我们真的别无选择。标量上下文是在 Perl 中获取数组长度的方法。
    猜你喜欢
    • 2021-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-13
    • 2020-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多