我想匹配 110110 但不是 10110。这意味着至少重复两次相同的连续数字。有任何正则表达式吗?
应该匹配:110110、123445446、12344544644
不应该匹配:10110、123445
/(\d)\1.*\1\1/
这匹配具有 2 个双数实例的字符串,即 11011 但不是 10011
\d
匹配任何数字
\1
匹配第一个匹配 有效地将第一个条目加倍
这也将匹配 1111。如果需要将 .* 更改为 .+ 之间的其他字符
哦,这看起来更整洁
((\d)\2).*\1
如果您想找到不匹配的值,但必须有 2 组双打,那么您只需要再次添加第一部分,如
((\d)\2).*((\d)\4)
括号意味着 $1 和 $3 将包含两位数,而 $2 和 $4 包含个位数(然后加倍)。
11233
$1=11
$2=1
$3=33
$4=3
如果我理解正确,您的正则表达式将是:
m{
(\d)\1 # First repeated pair
.* # Anything in between
(\d)\2 # Second repeated pair
}x
例如:
for my $x (qw(110110 123445446 12344544644 10110 123445)) {
my $m = $x =~ m{(\d)\1.*(\d)\2} ? "matches" : "does not match";
printf "%-11s : %s\n", $x, $m;
}
110110 : matches
123445446 : matches
12344544644 : matches
10110 : does not match
123445 : does not match
如果您正在谈论所有数字,则可以这样做:
00.*00|11.*11|22.*22|33.*33|44.*44|55.*55|66.*66|77.*77|88.*88|99.*99
它只是 9 种不同的模式 OR'ed 在一起,每个模式都检查至少两次出现的所需 2 位数模式。
使用 Perls 更高级的 RE,您可以使用以下两个连续数字两次:
(\d)\1.*\1\1
或者,正如您的评论之一所述,两个连续的数字后面跟着两个可能不相同的连续数字:
(\d)\1.*(\d)\2
如果我正确理解了您的问题,那么根据 regexbuddy(设置为使用 perl 语法),这将匹配 110110 但不匹配 10110:
(1{2})0\10
以下是更通用的,并且将匹配稍后在字符串中重复两个相等数字的任何字符串。
(\d{2})\d+\1\d*
以上将匹配以下示例:
110110 110011 112345611 2200022345
最后,要在一个字符串中找到两组两位数并且你不在乎它们在哪里,试试这个:
\d*?(\d{2})\d+?\1\d*
这将匹配上面的例子加上这个:
12345501355789
它是上面例子中匹配的两组双5。
[更新] 刚刚看到您将字符串与两个不同的两位数匹配的额外要求,试试这个:
\d*?(\d)\1\d*?(\d)\2\d*
这将匹配如下字符串:
12342202345567
12342202342267
请注意,22 和 55 导致第一个字符串匹配,而 22 对导致第二个字符串匹配。
没有理由在一个正则表达式中做所有事情......您也可以使用 Perl 的其余部分:
#!/usr/bin/perl -l
use strict;
use warnings;
my @strings = qw( 11233 110110 10110 123445 123445446 12344544644 );
print if is_wanted($_) for @strings;
sub is_wanted {
my ($s) = @_;
my @matches = $s =~ /(?<group>(?<first>[0-9])\k<first>)/g;
return 1 < @matches / 2;
}
__END__
根据您的数据如何,这是一种最小的正则表达式方式。
while(<DATA>){
chomp;
@s = split/\s+/;
foreach my $i (@s){
if( $i =~ /123445/ && length($i) ne 6){
print $_."\n";
}
}
}
__DATA__
This is a line
blah 123445446 blah
blah blah 12344544644 blah
.... 123445 ....
this is last line