(相当于)“字符类中的反向引用”的一般方法?

时间:2013-08-14 20:54:59

标签: regex perl backreference character-class

在Perl正则表达式中,\1\2等表达式通常被解释为先前捕获的组的“反向引用”,但\1,{{1}时则不然}等出现在一个字符类中。在后一种情况下,\2被视为转义字符(因此\只是\1等)。

因此,如果(例如)想要匹配一个字符串(长度大于1),其第一个字符与其最后一个字符匹配,但不出现在字符串中的任何其他位置,则以下正则表达式将不< / em> do:

1

工作,因为它匹配(例如)字符串/\A # match beginning of string; (.) # match and capture first character (referred to subsequently by \1); [^\1]* # (WRONG) match zero or more characters different from character in \1; \1 # match \1; \z # match the end of the string; /sx # s: let . match newline; x: ignore whitespace, allow comments

'a1a2a'

我通常可以设法找到一些解决方法 1 ,但它总是特定于问题,并且通常比我在字符类中使用反向引用时所做的更复杂。

是否有通用(并且希望直截了当)解决方法?


1 例如,对于上例中的问题,我会使用类似

的内容
  DB<1> ( 'a1a2a' =~ /\A(.)[^\1]*\1\z/ and print "fail!" ) or print "success!"
fail!

...我在早期的正则表达式中使用更加令人生畏的否定先行断言/\A (.) # match and capture first character (referred to subsequently # by \1); (?!.*\1\.+\z) # a negative lookahead assertion for "a suffix containing \1"; .* # substring not containing \1 (as guaranteed by the preceding # negative lookahead assertion); \1\z # match last character only if it is equal to the first one /sx 替换了相当简单(但是,唉,不正确)的子表达式[^\1]*。这个断言基本上是说“如果(?!.*\1.+\z)出现在这个点之外的任何地方(除了最后一个位置),就会放弃。”顺便说一下,我给出这个解决方案只是为了说明我在问题中提到的那种解决方法。我并不认为这是一个特别好的。

1 个答案:

答案 0 :(得分:12)

这可以通过重复组中的负向前瞻来实现:

/\A         # match beginning of string;
 (.)        # match and capture first character (referred to subsequently by \1);
 ((?!\1).)* # match zero or more characters different from character in \1;
 \1         # match \1;
 \z         # match the end of the string;
/sx

即使该组包含多个字符,也可以使用此模式。