使用正则表达式打印字母数字字符

Print alpha-numeric characters using regular expressions

我是正则表达式的新手。

我需要打印遵循以下模式的所有 8 个字符组合(字母数字)。

您可以检查每个模式。 让我们将字符串命名为 $str。从“00000000”到 "zzzzzzzz" 生成 $str 并使用以下 if 子句来选择与模式匹配的字符串。

if ($str =~ /^[A-Za-z][0-9]/        // pattern 1 and 2
  && $str !~ /[0-9]{3}/             // pattern 3
  && $str !~ /[A-Za-z]{4}/)         // pattern 4

正则表达式用于定义语法。匹配和替换运算符检查字符串是否匹配使用正则表达式定义的语法模式。我不知道有任何使用正则表达式模式生成字符串的工具。


当您有任意数量的嵌套循环时,您需要 Algorithm::LoopsNestedLoops。在您的情况下,循环的数量是固定的,但是循环数量太多以至于 NestedLoops 无论如何都会派上用场。

[我假设您只对 ASCII 中的字母和数字感兴趣。]

Naïve(生成所有序列,并过滤掉不需要的序列):

use Algorithm::Loops qw( NestedLoops );

my @syms = ('A'..'Z', 'a'..'z', '0'..'9');

my $iter = NestedLoops([ (\@syms) x 8 ]);

while (my @s = $iter->()) {
   my $s = join('', @s);
   next if $s !~ /^[a-zA-Z][0-9]/;
   next if $s =~ /[a-zA-Z]{4}|[0-9]{3}/;
   say $s;
}

大部分天真(生成除明显错误序列之外的所有序列,并过滤掉不需要的序列):

use Algorithm::Loops qw( NestedLoops );

my @letters = ('A'..'Z', 'a'..'z');
my @digits  = ('0'..'9');
my @syms    = (@letters, @digits);

my $iter = NestedLoops([
   \@letters,
   \@digits,
   (\@syms) x 6,
]);

while (my @s = $iter->()) {
   my $s = join('', @s);
   next if $s =~ /[a-zA-Z]{4}|[0-9]{3}/;
   say $s;
}

但这仍然会生成大量需要丢弃的字符串。下面只生成我们想要的字符串。它通过生成将产生所需字符串的模式(LDLLLDLLLDLLLDLDLDLLLDDLLDLLDLLL、...),然后从这些模式构建字符串来做到这一点。

高效的算法(这并不意味着实现是高效的):

use Algorithm::Loops qw( NestedLoops );

my @letters = ('A'..'Z', 'a'..'z');
my @digits  = ('0'..'9');

sub make_pat_gen_iter {
   my $raw_pat_gen_iter = NestedLoops([
      ['L'],
      ['D'],
      (['L','D']) x 6,
   ]);

   return sub {
      while (1) {
         my @pat = $raw_pat_gen_iter->();
         return () if !@pat;

         my $pat = join('', @pat);
         next if $pat =~ /L{4}|D{3}/;

         return @pat;
      }
   };
}

sub make_gen_iter {
   my $pat_gen_iter = make_pat_gen_iter();
   my @pat;

   my $gen_sub_iter;

   return sub {
      return () if !$pat_gen_iter;

      while (1) {
         if (!$gen_sub_iter) {
            @pat = $pat_gen_iter->();
            if (!@pat) {
               $pat_gen_iter = undef;
               return ();
            }

            $gen_sub_iter = NestedLoops([
               map { $_ eq 'L' ? \@letters : \@digits } @pat
            ]);
         }

         my @s = $gen_sub_iter->();
         if (!@s) {
            $gen_sub_iter = undef;
            next;
         }

         return join('', @s);
      }
   };
}

my $gen_iter = make_gen_iter();

while (defined( my $s = $gen_iter->() )) {
   say $s;
}

为了好玩,下面是模式迭代器的完整结果:

LDLLLDLL    LDLLLDLD    LDLLLDDL    LDLLDLLL    LDLLDLLD
LDLLDLDL    LDLLDLDD    LDLLDDLL    LDLLDDLD    LDLDLLLD
LDLDLLDL    LDLDLLDD    LDLDLDLL    LDLDLDLD    LDLDLDDL
LDLDDLLL    LDLDDLLD    LDLDDLDL    LDLDDLDD    LDDLLLDL
LDDLLLDD    LDDLLDLL    LDDLLDLD    LDDLLDDL    LDDLDLLL
LDDLDLLD    LDDLDLDL    LDDLDLDD    LDDLDDLL    LDDLDDLD