Perl模式匹配无法按预期工作

时间:2016-12-07 18:15:38

标签: regex perl

我正在尝试使用正则表达式匹配可能以逗号分隔的值。基本上,如果字符串中的任何值在第3位开始没有3g或3k,我想返回true。

我的测试代码如下:

my @a = ('in3g123456,dh3k123456,dhec110101','dhec110101,dhec123456','in3g123456,dh3k123456', 'c3kasdf', 'usdfusdufs3gsdf' );

foreach (@a) {
  print $_;
  say $_ =~ /(?:^|,)\w{2}[^(?:3G|3K)]/i ? " true" : " false";
}

返回

in3g123456,dh3k123456,dhec110101 true
dhec110101,dhec123456 true
in3g123456,dh3k123456 false
c3kasdf false   <- whaaaaaaaat?
usdfusdufs3gsdf true

我不明白为什么第四个不是真的。任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:2)

HttpMessage.toStrict读为“[^(?:3G|3K)](等任何字符”

?

使用此:

                      failed
                      v
        c3            kasdf
/(?:^|,)\w{2}[^(?:3G|3K)]/i

演示:https://regex101.com/r/P2XsgN/1

答案 1 :(得分:1)

/\b\w{2}(?!3g|3k)/i

怎么样?

\b匹配单词开头或结尾的空字符串。在这种情况下,相当于(^|,)稍微简单一些。

(?!foo)是一个零宽度的负前瞻断言。因此,匹配空字符串,只要它后面没有匹配foo的子字符串。

答案 2 :(得分:1)

您还可以先split字符串,而不是使用正则表达式解析所有内容。这更灵活,更易于维护,也更容易。

处理提取的“值”列表时,您可以将任意字符与模式/^..$patt/匹配两次。模块List::MoreUtils对于列表操作非常有用(并且快速),并且notall函数是根据您的条件量身定制的。

use warnings 'all';
use strict;
use List::MoreUtils qw(notall);

my $file = '...';
open my $fh, '<', $file or die "Can't open $file: $!";

while (<$fh>)
{
    my $res = notall { /^..(?:3k|3g)/ } split /,/;

    print "$_: " . ($res ? 'true' : 'false'), "\n";
}

我认为你从一个文件中读取。如果没有,请将while (<$fn>)替换为for (@strings)

如果列表中的任何元素未通过条件,则notall函数返回true。

split默认使用$_,因此我们只需要该模式。这里只是,,但模式采用正则表达式,因此可以灵活地匹配分隔符。例如,此/[,\s]+/会分割任意数量的,和/或空格。因此,字符串中的,, ,匹配为分隔符,以及,或空格。

当使用字符串应用于数组时,上面打印

in3g123456,dh3k123456,dhec110101: true
dhec110101,dhec123456: true
in3g123456,dh3k123456: false
c3kasdf: true
usdfusdufs3gsdf: true

答案 3 :(得分:0)

您可以使用substr获取第3和第4位的数据,然后将其与(3g|3k)进行比较。

substr $_,2,2
#!/usr/bin/perl
use strict;
use warnings;

my @a = ('in3g123456,dh3k123456,dhec110101','dhec110101,dhec123456','in3g123456,dh3k123456', 'c3kasdf', 'usdfusdufs3gsdf' );

foreach (@a) {
  my @inputs = split /,/,$_;
  my $flag = 0;
  foreach (@inputs){
    $flag = 1 unless ((substr $_,2,2) =~ /(3g|3k)/);
  }
  $flag ? print "$_: True\n" : print "$_: False\n";
}

输出:

in3g123456,dh3k123456,dhec110101: True
dhec110101,dhec123456: True
in3g123456,dh3k123456: False
c3kasdf: True
usdfusdufs3gsdf: True

Demo