I want to understand how can I do arithmetic on matched sub-patterns in perl regex. This is just a sample code and I want to understand how can I use \1
(already matched sub-pattern. in this case - 7) to match pattern+1
(8)
我想了解如何在perl regex中对匹配的子模式进行算术运算。这只是一个示例代码,我想了解如何使用\ 1(已经匹配的子模式。在这种情况下为7)来匹配模式+ 1(8)
my $y = 77668;
if($y =~ /(\d)\1(\d)\2\1+1/) #How to increment a previously
#matched sub-pattern and form a pattern?
{
print $y;
}
EDIT
From the answers, I see that pattern arithmetic is not possible.
从答案中,我看到模式算法是不可能的。
This is what I want to achieve.
I want to form a regex which will match this pattern:
这就是我想要实现的目标。我想形成一个匹配这种模式的正则表达式:
N-3N-2N-1NNN+1N+2N+3 (N = 3,4,5,6
2 个解决方案
#1
6
Its possible via regex code blocks:
它可能通过正则表达式代码块:
my $y = 77668;
if($y =~ /(\d)\1(\d)\2(??{$1+1})/ ) {
print $y;
}
In this snippet (??{ CODE })
returns another regex that must match, so this regex looks like "8" ($1+1). As a result, whole regex will match only if 5th digit is greather and 1st by 1. But drawback with 1st digit is 9, this code block will return "10", so possible its wrong behavior, but you said nothing about what must be done in this case.
在这个片段(?? {CODE})中返回另一个必须匹配的正则表达式,因此这个正则表达式看起来像“8”($ 1 + 1)。因此,整个正则表达式只有在第5位数更好且第1位数为1时才匹配。但第1位数的缺点是9,此代码块将返回“10”,因此可能出现错误行为,但您没有说什么必须是在这种情况下完成。
Now about N-3N-2N-1NNN+1N+2N+3
question, you can match it with this regex:
现在关于N-3N-2N-1NNN + 1N + 2N + 3的问题,你可以将它与这个正则表达式匹配:
my $n = 5;
if( $y =~ /(??{ ($n-3).($n-2).($n-1).$n.($n+1).($n+2).($n+3) })/ ){
Or more "scalable" way:
或者更“可扩展”的方式:
my $n = 5;
if( $y =~ /(??{ $s=''; $s .= $n+$_ foreach(-3..3); $s; })/ ){
Again, what we must do if $n == 2 ?? $n-3 will be -1. Its not a simply digit cus it have sign, so you should think about this cases.
再次,如果$ n == 2,我们必须做什么? $ n-3将为-1。它不是一个简单的数字cus它有标志,所以你应该考虑这种情况。
One another way. Match what we have and then check it.
另一种方式。匹配我们拥有的,然后检查它。
if( $y =~ /(\d)(\d)(\d)(\d)(\d)(\d)(\d)/ ) {
if( $1 == ($4-3) && $2 == ($4-2) && $3 == ($4-1) && $6 == ($4+1) && $7 == ($4+2) && $7 == ($4+3) ) {
#...
Seems this method litle bit clumsy, but its obivious to everyone (i hope).
似乎这种方法痘痘有点笨拙,但它对每个人都很鄙视(我希望)。
Also, you can optimize your regex since 7 ascending digits streak is not so frequent combination, plus get some lulz from co-workers xD:
此外,你可以优化你的正则表达式,因为7个升序数字条纹不是那么频繁的组合,加上来自同事xD的一些lulz:
sub check_number {
my $i;
for($i=1; $i<length($^N); $i++) {
last if substr($^N, $i, 1)<=substr($^N, $i-1, 1);
}
return $i<length($^N) ? "(*FAIL)" : "(*ACCEPT)";
}
if( $y =~ /[0123][1234][2345][3456][4567][5678][6789](??{ check_number() })/ ) {
Or... Maybe most human-friendly method:
或者......也许最人性化的方法:
if( $y =~ /0123456|1234567|2345678|3456789/ ) {
Seems last variant is bingo xD Its good example about not searching regex when things are so simple)
似乎最后一个变种是bingo xD它是关于在事情如此简单时不搜索正则表达式的好例子)
#2
6
Of course this is possible. We are talking about Perl regexes after all. But it will be rather ugly:
当然这是可能的。毕竟我们正在谈论Perl正则表达式。但它会相当难看:
say "55336"=~m{(\d)\1(\d)\2(\d)(?(?{$1+1==$3})|(*F))}?"match":"fail";
or pretty-printed:
say "55336" =~ m{ (\d)\1 (\d)\2 (\d)
(? (?{$1+1==$3}) # true-branch: nothing
|(*FAIL)
)
}x
? "match" : "fail";
What does this do? We collect the digits in ordinary captures. At the end, we use an if-else pattern:
这是做什么的?我们收集普通捕获中的数字。最后,我们使用if-else模式:
(? (CONDITION) TRUE | FALSE )
We can embed code into a regex with (?{ code })
. The return value of this code can be used as a condition. The (*FAIL)
(short: (*F)
) verb causes the match to fail. Use (*PRUNE)
if you only want a branch, not the whole pattern to fail.
我们可以使用(?{code})将代码嵌入到正则表达式中。此代码的返回值可用作条件。 (* FAIL)(短:(* F))动词导致匹配失败。如果您只想要一个分支,请使用(* PRUNE),而不是整个模式失败。
Embedded code is also great for debugging. However, older perls cannot use regexes inside this regex code :-(
嵌入式代码也非常适合调试。但是,旧的perls不能在这个正则表达式代码中使用正则表达式:-(
So we can match lots of stuff and test it for validity inside the pattern itself. However, it might be a better idea to do that outside of the pattern like:
所以我们可以匹配很多东西,并在模式本身内测试它的有效性。但是,在模式之外执行此操作可能更好:
"string" =~ /regex/ and (conditions)
Now to your main pattern N-3N-2N-1NNN+1N+2N+3
(I hope I parsed it correctly):
现在你的主要模式N-3N-2N-1NNN + 1N + 2N + 3(我希望我正确解析它):
my $super_regex = qr{
# N -3 N-2 N-1 N N N+1 N+2 N+3
(\d)-3\1-2\1-1\1\1(\d)(\d)(\d)
(?(?{$1==$2-1 and $1==$3-2 and $1==$4-3})|(*F))
}x;
say "4-34-24-144567" =~ $super_regex ? "match" : "fail";
Or did you mean
或者你的意思是
my $super_regex = qr{
#N-3 N-2 N-1 N N N+1 N+2 N+3
(\d)(\d)(\d) (\d)\4 (\d)(\d)(\d)
(? (?{$1==$4-3 and $2==$4-2 and $3==$4-1 and
$5==$4+1 and $6==$4+2 and $7==$4+3})|(*F))
}x;
say "123445678" =~ $super_regex ? "match" : "fail";
The scary thing is that these even works (with perl 5.12).
可怕的是,这些甚至可以工作(使用perl 5.12)。
We could also generate parts of the pattern at match-time with the (??{ code })
construct — the return value of this code is used as a pattern:
我们还可以在匹配时使用(?? {code})构造生成模式的一部分 - 此代码的返回值用作模式:
my $super_regex = qr{(\d)(??{$1+1})(??{$1+2})}x;
say "234"=~$super_regex ? "match":"fail"
et cetera. However, I think readability suffers more this way.
等等。但是,我认为可读性受此影响更大。
If you need more than nine captures, you can use named captures with the
如果您需要超过9次捕获,则可以使用命名捕获
(?<named>pattern) ... \k<named>
constructs. The contents are also available in the %+
hash, see perlvar for that.
结构体。内容也可以在%+哈希中找到,请参阅perlvar。
To dive further into the secrets of Perl regexes, I recommend reading perlre a few times.
为了进一步深入了解Perl正则表达式的秘密,我建议阅读perlre几次。
#1
6
Its possible via regex code blocks:
它可能通过正则表达式代码块:
my $y = 77668;
if($y =~ /(\d)\1(\d)\2(??{$1+1})/ ) {
print $y;
}
In this snippet (??{ CODE })
returns another regex that must match, so this regex looks like "8" ($1+1). As a result, whole regex will match only if 5th digit is greather and 1st by 1. But drawback with 1st digit is 9, this code block will return "10", so possible its wrong behavior, but you said nothing about what must be done in this case.
在这个片段(?? {CODE})中返回另一个必须匹配的正则表达式,因此这个正则表达式看起来像“8”($ 1 + 1)。因此,整个正则表达式只有在第5位数更好且第1位数为1时才匹配。但第1位数的缺点是9,此代码块将返回“10”,因此可能出现错误行为,但您没有说什么必须是在这种情况下完成。
Now about N-3N-2N-1NNN+1N+2N+3
question, you can match it with this regex:
现在关于N-3N-2N-1NNN + 1N + 2N + 3的问题,你可以将它与这个正则表达式匹配:
my $n = 5;
if( $y =~ /(??{ ($n-3).($n-2).($n-1).$n.($n+1).($n+2).($n+3) })/ ){
Or more "scalable" way:
或者更“可扩展”的方式:
my $n = 5;
if( $y =~ /(??{ $s=''; $s .= $n+$_ foreach(-3..3); $s; })/ ){
Again, what we must do if $n == 2 ?? $n-3 will be -1. Its not a simply digit cus it have sign, so you should think about this cases.
再次,如果$ n == 2,我们必须做什么? $ n-3将为-1。它不是一个简单的数字cus它有标志,所以你应该考虑这种情况。
One another way. Match what we have and then check it.
另一种方式。匹配我们拥有的,然后检查它。
if( $y =~ /(\d)(\d)(\d)(\d)(\d)(\d)(\d)/ ) {
if( $1 == ($4-3) && $2 == ($4-2) && $3 == ($4-1) && $6 == ($4+1) && $7 == ($4+2) && $7 == ($4+3) ) {
#...
Seems this method litle bit clumsy, but its obivious to everyone (i hope).
似乎这种方法痘痘有点笨拙,但它对每个人都很鄙视(我希望)。
Also, you can optimize your regex since 7 ascending digits streak is not so frequent combination, plus get some lulz from co-workers xD:
此外,你可以优化你的正则表达式,因为7个升序数字条纹不是那么频繁的组合,加上来自同事xD的一些lulz:
sub check_number {
my $i;
for($i=1; $i<length($^N); $i++) {
last if substr($^N, $i, 1)<=substr($^N, $i-1, 1);
}
return $i<length($^N) ? "(*FAIL)" : "(*ACCEPT)";
}
if( $y =~ /[0123][1234][2345][3456][4567][5678][6789](??{ check_number() })/ ) {
Or... Maybe most human-friendly method:
或者......也许最人性化的方法:
if( $y =~ /0123456|1234567|2345678|3456789/ ) {
Seems last variant is bingo xD Its good example about not searching regex when things are so simple)
似乎最后一个变种是bingo xD它是关于在事情如此简单时不搜索正则表达式的好例子)
#2
6
Of course this is possible. We are talking about Perl regexes after all. But it will be rather ugly:
当然这是可能的。毕竟我们正在谈论Perl正则表达式。但它会相当难看:
say "55336"=~m{(\d)\1(\d)\2(\d)(?(?{$1+1==$3})|(*F))}?"match":"fail";
or pretty-printed:
say "55336" =~ m{ (\d)\1 (\d)\2 (\d)
(? (?{$1+1==$3}) # true-branch: nothing
|(*FAIL)
)
}x
? "match" : "fail";
What does this do? We collect the digits in ordinary captures. At the end, we use an if-else pattern:
这是做什么的?我们收集普通捕获中的数字。最后,我们使用if-else模式:
(? (CONDITION) TRUE | FALSE )
We can embed code into a regex with (?{ code })
. The return value of this code can be used as a condition. The (*FAIL)
(short: (*F)
) verb causes the match to fail. Use (*PRUNE)
if you only want a branch, not the whole pattern to fail.
我们可以使用(?{code})将代码嵌入到正则表达式中。此代码的返回值可用作条件。 (* FAIL)(短:(* F))动词导致匹配失败。如果您只想要一个分支,请使用(* PRUNE),而不是整个模式失败。
Embedded code is also great for debugging. However, older perls cannot use regexes inside this regex code :-(
嵌入式代码也非常适合调试。但是,旧的perls不能在这个正则表达式代码中使用正则表达式:-(
So we can match lots of stuff and test it for validity inside the pattern itself. However, it might be a better idea to do that outside of the pattern like:
所以我们可以匹配很多东西,并在模式本身内测试它的有效性。但是,在模式之外执行此操作可能更好:
"string" =~ /regex/ and (conditions)
Now to your main pattern N-3N-2N-1NNN+1N+2N+3
(I hope I parsed it correctly):
现在你的主要模式N-3N-2N-1NNN + 1N + 2N + 3(我希望我正确解析它):
my $super_regex = qr{
# N -3 N-2 N-1 N N N+1 N+2 N+3
(\d)-3\1-2\1-1\1\1(\d)(\d)(\d)
(?(?{$1==$2-1 and $1==$3-2 and $1==$4-3})|(*F))
}x;
say "4-34-24-144567" =~ $super_regex ? "match" : "fail";
Or did you mean
或者你的意思是
my $super_regex = qr{
#N-3 N-2 N-1 N N N+1 N+2 N+3
(\d)(\d)(\d) (\d)\4 (\d)(\d)(\d)
(? (?{$1==$4-3 and $2==$4-2 and $3==$4-1 and
$5==$4+1 and $6==$4+2 and $7==$4+3})|(*F))
}x;
say "123445678" =~ $super_regex ? "match" : "fail";
The scary thing is that these even works (with perl 5.12).
可怕的是,这些甚至可以工作(使用perl 5.12)。
We could also generate parts of the pattern at match-time with the (??{ code })
construct — the return value of this code is used as a pattern:
我们还可以在匹配时使用(?? {code})构造生成模式的一部分 - 此代码的返回值用作模式:
my $super_regex = qr{(\d)(??{$1+1})(??{$1+2})}x;
say "234"=~$super_regex ? "match":"fail"
et cetera. However, I think readability suffers more this way.
等等。但是,我认为可读性受此影响更大。
If you need more than nine captures, you can use named captures with the
如果您需要超过9次捕获,则可以使用命名捕获
(?<named>pattern) ... \k<named>
constructs. The contents are also available in the %+
hash, see perlvar for that.
结构体。内容也可以在%+哈希中找到,请参阅perlvar。
To dive further into the secrets of Perl regexes, I recommend reading perlre a few times.
为了进一步深入了解Perl正则表达式的秘密,我建议阅读perlre几次。