Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex Perl正则表达式多重匹配_Regex_Perl_Backreference - Fatal编程技术网

Regex Perl正则表达式多重匹配

Regex Perl正则表达式多重匹配,regex,perl,backreference,Regex,Perl,Backreference,我正在寻找一个正则表达式,其行为如下: 输入:“你好,世界。” 输出:he、el、ll、lo、wo或rl、ld 我的想法大致是 while($string =~ m/(([a-zA-Z])([a-zA-Z]))/g) { print "$1-$2 "; } 但这有点不同。这很棘手。你必须捕获它,保存它,然后强制回溯 您可以这样做: use v5.10; # first release with backtracking control verbs my $

我正在寻找一个正则表达式,其行为如下:

输入:“你好,世界。”

输出:he、el、ll、lo、wo或rl、ld

我的想法大致是

    while($string =~ m/(([a-zA-Z])([a-zA-Z]))/g) {
        print "$1-$2 ";
    }

但这有点不同。

这很棘手。你必须捕获它,保存它,然后强制回溯

您可以这样做:

use v5.10;   # first release with backtracking control verbs

my $string = "hello, world!";
my @saved;

my $pat = qr{
    ( \pL {2} )
    (?{ push @saved, $^N })
    (*FAIL)
}x;

@saved = ();
$string =~ $pat;
my $count = @saved;
printf "Found %d matches: %s.\n", $count, join(", " => @saved);
产生以下结果:

找到8个匹配项:he、el、ll、lo、wo、or、rl、ld。
如果您没有v5.10或头痛,可以使用以下方法:

my $string = "hello, world!";
my @pairs = $string =~ m{
  # we can only match at positions where the
  # following sneak-ahead assertion is true:
    (?=                 # zero-width look ahead
        (               # begin stealth capture
            \pL {2}     #       save off two letters
        )               # end stealth capture
    )
  # succeed after matching nothing, force reset
}xg;

my $count = @pairs;
printf "Found %d matches: %s.\n", $count, join(", " => @pairs);
这将产生与以前相同的输出


但是你可能还是会头疼。

我会在“前瞻”中使用捕获的

(?=([a-zA-Z]{2}))
    ------------
         |->group 1 captures two English letters 
试试看

无需“强制回溯”

尽管您可能希望匹配任何字母,而不是指定的有限集合

push @pairs, "$1$2" while /(\pL)(?=(\pL))/g;

您可以通过查找字母并使用
pos
函数利用捕获的位置,
\G
在另一个正则表达式中引用它,以及
substr
从字符串中读取几个字符来完成此操作

use v5.10;
use strict;
use warnings;

my $letter_re = qr/[a-zA-Z]/;

my $string = "hello world.";
while( $string =~ m{ ($letter_re) }gx ) {
    # Skip it if the next character isn't a letter
    # \G will match where the last m//g left off.
    # It's pos() in a regex.
    next unless $string =~ /\G $letter_re /x;

    # pos() is still where the last m//g left off.
    # Use substr to print the character before it (the one we matched)
    # and the next one, which we know to be a letter.
    say substr $string, pos($string)-1, 2;
}
您可以将“检查下一个字母”逻辑放入带有零宽度肯定断言的原始正则表达式中,
(?=pattern)
。零宽度意味着它不会被捕获,也不会提升
m//g
regex的位置。这有点紧凑,但零宽度断言可能会变得棘手

while( $string =~ m{ ($letter_re) (?=$letter_re) }gx ) {
    # pos() is still where the last m//g left off.
    # Use substr to print the character before it (the one we matched)
    # and the next one, which we know to be a letter.
    say substr $string, pos($string)-1, 2;
}
更新:我最初试图将匹配和前瞻捕获为
m{($letter_re(?=$letter_re))}gx
,但没有成功。向前看是零宽度并且滑出比赛。其他人的回答表明,如果你在“展望”中加入第二个捕获,那么它可能会崩溃到

say "$1$2" while $string =~ m{ ($letter_re) (?=($letter_re)) }gx;

我把所有答案留给TMTOWTDI,特别是如果你不是正则表达式大师的话。

还有另一种方法。不使用任何regexp魔术,它确实使用嵌套的
map
s,但如果需要,可以很容易地将其转换为
for
循环

#!/usr/bin/env perl

use strict;
use warnings;

my $in = "hello world.";
my @words = $in =~ /(\b\pL+\b)/g;

my @out = map {
  my @chars = split '';
  map { $chars[$_] . $chars[$_+1] } ( 0 .. $#chars - 1 );
} @words;

print join ',', @out;
print "\n";

同样,对我来说,这比一个奇怪的正则表达式YMMV更易读。

好问题。我想我以前可能已经回答过了。对于
(*失败)
。回答得不错。你能简单地解释一下答案吗?@KrishnachandraSharma,嗯,我想我有。捕获它,将其保存在外部变量中,然后强制失败。故障回溯,引擎向前一步,因为它没有进展,我们再试一次。起泡、冲洗、重复。很好的方法和答案,但这在旧版本的Perl 5.10中会出现问题。谢谢,我认为会有一种更直接的方法,但它完成了工作。
(?{})
在编译regex时捕获,这是在编译时。因此,这使它像一个命名的sub。在将其移动到sub之前,实际上没有问题,但当您移动到sub时,您将得到
变量“@saved”不可用
效果很好。回答得好,“字母表”是什么?希腊语是字母表。拉丁语是字母表。西里尔语是一种字母表。不捕捉“字母表”;捕获A和Z(包括A和Z)之间的两个大写或小写字母。它在立面之类的东西上失败了。@tchrist op从来没有提到过……a-zA-Z仍然是alphabets@Some1.Kill.The.DJ嗯,这不是英文字母表的意思。我建议你查一本字典。@tchrist hope英文字母表让你更清楚:首先,PNot效率不高。你知道,那有可怕的“
[a-Z]
代码气味”。有利于避免墨西哥辣椒,不利于正常文本。@tchrist,op从未提及任何关于字母的内容,但增加了
\pL
。我总是使用
\pL
,除非我在专门规定a-Z的RFC工作。我希望我记得
(*FAIL)
在前瞻技术之外还有什么好处。@tchrist,也用于条件句
(?({condition()})(?!)
你真的使用
substr
pos
?尤其像这样?我几乎从来没有这样做过。一部分原因是因为它对我怀有敌意,但主要原因是它很微妙。@tchrist在这种情况下,这似乎是最简单的方法
pos
substr
的优点是能够直截了当地理解vs带有look aheads和capture的正则表达式。我同意,
pos
可以神秘地从你下面变出来,但小范围可以原谅许多罪恶。我的第一个冲动是一个非正则表达式的迭代解决方案,因为如果循环遍历字符,“匹配每一对字母”非常简单。我试着用捕获+前瞻的方式来实现它,但没能成功;我没有意识到你需要在《展望》中,而不是在它的周围,放上第二张照片。我读的越多,我就越觉得池上春树的作品更清晰。
#!/usr/bin/env perl

use strict;
use warnings;

my $in = "hello world.";
my @words = $in =~ /(\b\pL+\b)/g;

my @out = map {
  my @chars = split '';
  map { $chars[$_] . $chars[$_+1] } ( 0 .. $#chars - 1 );
} @words;

print join ',', @out;
print "\n";