使用反向引用的字母顺序正则表达式

时间:2017-06-30 14:33:21

标签: regex backreference character-class

我最近遇到了一个难题,找到了匹配的正则表达式:

  

5个字符长的字符串,由按字母顺序升序的小写英文字母组成

有效示例包括:

aaaaa
abcde
xxyyz
ghost
chips
demos

无效的示例包括:

abCde
xxyyzz
hgost
chps

我目前的解决方案是kludgy。我使用正则表达式:

(?=^[a-z]{5}$)^(a*b*c*d*e*f*g*h*i*j*k*l*m*n*o*p*q*r*s*t*u*v*w*x*y*z*)$

使用非消费捕获组断言字符串长度为5,然后验证字符串是否按顺序包含小写英文字母(see Rubular)。

相反,我想在字符类中使用反向引用。类似的东西:

^([a-z])([\1-z])([\2-z])([\3-z])([\4-z])$

我脑子里的解决方案(see Rubular)的逻辑是捕获第一个字符[a-z],在第二个字符类中使用它作为backrefence,依此类推。但是,\1\2 ...在字符类中似乎引用了1到2的ASCII值...有效地匹配任何四个或五个字符的字符串。

我有两个问题:

  1. 我可以在字符类中使用反向引用来检查升序字符串吗?
  2. 这个谜题是否有任何不太苛刻的解决方案?

4 个答案:

答案 0 :(得分:4)

我将此答案更多地作为评论而不是答案发布,因为它的格式比评论更好。

与您的问题相关:

  
      
  1. 我可以在字符类中使用反向引用来检查升序字符串吗?
  2.   
不,你不能。如果你看一下backref regular-expressions部分,你会发现以下文档:

  

不能在字符类内使用括号和反向引用

     

括号不能在字符类中使用,至少不能作为元字符使用。将括号放在字符类中时,它将被视为文字字符。所以正则表达式[(a)b]匹配a,b,(和)。

     

反向引用也不能在字符类中使用。像(a)[\ 1b]这样的正则表达式中的\ 1是错误或不必要的转义文字1 。在JavaScript中,它是一个八进制转义。

关于你的第二个问题:

  
      
  1. 这个谜题是否有任何不太苛刻的解决方案?
  2.   
Imho,你的正则表达式非常好,你可以在一开始就缩短它,就像这样:

(?=^.{5}$)^a*b*c*d*e*f*g*h*i*j*k*l*m*n*o*p*q*r*s*t*u*v*w*x*y*z*$
    ^--- Here

<强> Regex demo

答案 1 :(得分:3)

如果您愿意使用Perl(!),这将有效:

/^([a-z])((??{"[$1-z]"}))((??{"[$2-z]"}))((??{"[$3-z]"}))(??{"[$4-z]"})$/

答案 2 :(得分:2)

由于有人用Perl打破了冰,这是一个 Perl解决方案我猜..

请注意,这是一个基本的非正则表达式解决方案恰好是
塞进Perl正则表达式中的代码构造 有趣的是,如果有一天你需要协同作用来 正则表达式/代码这是一个不错的选择 那么您可以使用而不是简单的[a-z]字符代替 在它的位置使用一个非常复杂的模式,并使用支票与最后一个 这就是力量!!

正则表达式^(?:([a-z])(?(?{ $last gt $1 })(?!)|(?{ $last = $1 }))){5}$

Perl代码

use strict;
use warnings;


$/ = "";

my @DAry = split /\s+/, <DATA>;

my $last;

for (@DAry)
{
    $last = '';
    if ( 
      /
         ^                             # BOS
         (?:                           # Cluster begin
              ( [a-z] )                     # (1), Single a-z letter
                                            # Code conditional
              (?(?{
                   $last gt $1                  # last > current ?
                })
                   (?!)                          # Fail
                |                              # else,
                   (?{ $last = $1 })             # Assign last = current
              )
         ){5}                          # Cluster end, do 5 times
         $                             # EOS
      /x )
    {
        print "good   $_\n";
    }
    else {
        print "bad    $_\n";
    }
}

__DATA__

aaaaa
abcde
xxyyz
ghost
chips
demos
abCde
xxyyzz
hgost
chps

输出

good   aaaaa
good   abcde
good   xxyyz
good   ghost
good   chips
good   demos
bad    abCde
bad    xxyyzz
bad    hgost
bad    chps

答案 3 :(得分:2)

啊,好吧,它是一个有限的集合,所以你总是可以用交替来枚举它!这会发出强大的力量&#34;一点relx in perl REPL:

#include <stdio.h>

int main(void) {
  printf("while (<>) { if (/^(?:");
  for (int a = 'a'; a <= 'z'; ++a)
    for (int b = a; b <= 'z'; ++b)
      for (int c = b; c <= 'z'; ++c) {
        for (int d = c; d <= 'y'; ++d)
          printf("%c%c%c%c[%c-z]|", a, b, c, d, d);
        printf("%c%c%czz", a, b, c);
        if (a != 'z' || b != 'z' || c != 'z') printf("|\n");
      }
  printf(")$/x) { print \"Match!\\n\" } else { print \"No match.\\n\" }}\n");
  return 0;
}

现在:

$ gcc r.c
$ ./a.out > foo.pl
$ cat > data.txt
aaaaa
abcde
xxyyz
ghost
chips
demos
abCde
xxyyzz
hgost
chps
^D
$ perl foo.pl < data.txt
Match!
Match!
Match!
Match!
Match!
Match!
No match.
No match.
No match.
No match.

正则表达式只有220K左右; - )