我正在尝试使用正则表达式匹配可能以逗号分隔的值。基本上,如果字符串中的任何值在第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
我不明白为什么第四个不是真的。任何帮助将不胜感激。
答案 0 :(得分:2)
HttpMessage.toStrict
读为“[^(?:3G|3K)]
,(
等任何字符”
?
使用此:
failed
v
c3 kasdf
/(?:^|,)\w{2}[^(?:3G|3K)]/i
答案 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