标签: nested-reference

我们如何匹配^ nb ^ n与Java正则表达式?

这是一系列教育正则表达式文章的第二部分.它显示了向前看符号和嵌套引用如何可以用来匹配非正规languge ñ b ñ.嵌套引用首先介绍在:这个正则表达式如何找到三角形数字?

其中一种原型非常规语言是:

L = { añ bñ: n > 0 }

这是所有非空字符串的语言,由一些数字a后跟相同数量的字符串组成b.在这个语言字符串的例子有ab,aabb,aaabbb.

这种语言可以通过泵浦引理显示为非规则的.它实际上是一种原型上下文无关语言,可以通过无上下文语法 生成S ? aSb | ab.

尽管如此,现代正则表达式实现清楚地认识到的不仅仅是常规语言.也就是说,它们不是形式语言理论定义的"规则".PCRE和Perl支持递归正则表达式,.NET支持平衡组定义.更少的"花哨"特征,例如反向引用匹配,意味着正则表达式不规则.

但这个"基本"功能有多强大?L例如,我们可以用Java正则表达式识别吗?我们也许可以结合lookarounds和嵌套引用,并具有与如工作模式String.matches来匹配字符串一样ab,aabb,aaabbb,等?

参考

相关问题

java regex lookaround capturing-group nested-reference

94
推荐指数
3
解决办法
1万
查看次数

这个正则表达式如何找到三角形数字?

这是一系列教育正则表达式文章的一部分,这是对嵌套引用概念的温和介绍.

前几个三角形数字是:

 1 = 1
 3 = 1 + 2
 6 = 1 + 2 + 3
10 = 1 + 2 + 3 + 4
15 = 1 + 2 + 3 + 4 + 5
Run Code Online (Sandbox Code Playgroud)

有很多方法可以检查数字是否为三角形.有一种有趣的技术使用正则表达式如下:

  • 给定n,我们首先创建一个长度为n的字符串,其中填充相同的字符
  • 然后我们将此字符串与模式匹配 ^(\1.|^.)+$
    • 当且仅当此模式与字符串匹配时,n为三角形

以下是一些片段,表明它适用于多种语言:

PHP(在ideone.com上)

$r = '/^(\1.|^.)+$/';

foreach (range(0,50) as $n) {
  if (preg_match($r, str_repeat('o', $n))) {
     print("$n ");
  }
}
Run Code Online (Sandbox Code Playgroud)

Java(在ideone.com上)

for (int n = 0; n <= 50; …
Run Code Online (Sandbox Code Playgroud)

c# java regex capturing-group nested-reference

42
推荐指数
1
解决办法
2253
查看次数

这个Java正则表达式如何检测回文?

这是一系列教育正则表达式文章的第三部分.它遵循这个正则表达式如何找到三角形数字?(首先介绍嵌套引用)和如何将^ nb ^ n与Java正则表达式匹配? (前瞻性"计数"机制进一步详述).这部分介绍了一种特定形式的嵌套断言,当与嵌套引用结合使用时,Java正则表达式可以匹配大多数人认为"不可能"的东西:回文!

回文的语言是非常规的 ; 它实际上是无上下文的(对于给定的字母表).也就是说,现代正则表达式实现不仅仅识别常规语言,Perl/PCRE的递归模式和.NET的平衡组可以很容易地识别回文(参见:相关问题).

但是,Java的正则表达式引擎既不支持这些"高级"功能.然而"某人" (*wink*)成功编写了以下正则表达式,这似乎做得很好(参见ideone.com):

public class Palindrome {
    // asserts that the entirety of the string matches the given pattern
    static String assertEntirety(String pattern) {
        return "(?<=(?=^pattern$).*)".replace("pattern", pattern);
    }

    public static void main(String[] args) {
        final String PALINDROME =
            "(?x) | (?:(.) add)+ chk"
                .replace("add", assertEntirety(".*? (\\1 \\2?)"))
                .replace("chk", assertEntirety("\\2"));

        System.out.println(PALINDROME);
        // (?x) | (?:(.) (?<=(?=^.*? (\1 \2?)$).*))+ (?<=(?=^\2$).*)

        String[] tests …
Run Code Online (Sandbox Code Playgroud)

java regex palindrome lookaround nested-reference

21
推荐指数
1
解决办法
5555
查看次数

这种PCRE模式如何检测回文?

这个问题是在PCRE模式中使用前瞻,嵌套引用和条件来匹配所有回文的教育演示,包括PCRE手册页中给出的递归模式无法匹配的回文.

在PHP代码段中检查此PCRE模式:

$palindrome = '/(?x)
^
  (?:
      (.) (?=
              .*
              (
                \1
                (?(2) \2 | )
              )
              $
          )
  )*
  .?
  \2?
$


/';
Run Code Online (Sandbox Code Playgroud)

这种模式似乎可以检测到回文,如本测试案例所示(另见ideone.com):

$tests = array(
  # palindromes
  '',
  'a',
  'aa',
  'aaa',
  'aba',
  'aaaa',
  'abba',
  'aaaaa',
  'abcba',
  'ababa',

  # non-palindromes
  'aab',
  'abab',
  'xyz',
);

foreach ($tests as $test) {
  echo sprintf("%s '%s'\n", preg_match($palindrome, $test), $test);  
}
Run Code Online (Sandbox Code Playgroud)

那么这种模式如何运作?


笔记

此模式使用嵌套引用,这是此Java正则表达式如何检测回文中使用的类似技术,但与Java模式不同,没有外观(但确实使用了条件).

另请注意,PCRE 手册页提供了一个递归模式以匹配一些回文:

# the recursive pattern to detect …
Run Code Online (Sandbox Code Playgroud)

php regex pcre palindrome nested-reference

20
推荐指数
1
解决办法
1350
查看次数

为什么Java正则表达式引擎会在+重复上抛出StringIndexOutOfBoundsException?

我写了一个正则表达式模式来找到Fibonacci数字(没关系,为什么,我刚刚做了).它按预期工作得非常好(参见ideone.com):

    String FIBONACCI = 
        "(?x) .{0,2} | (?: (?=(\\2?)) (?=(\\2\\3|^.)) (?=(\\1)) \\2)++ . ";

    for (int n = 0; n < 1000; n++) {
        String s = new String(new char[n]);
        if (s.matches(FIBONACCI)) {
            System.out.print(n + " ");
        }
    } // 0 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 
Run Code Online (Sandbox Code Playgroud)

一个占有欲重复(即++主"回路")是至关重要的,因为你不希望这种匹配算法回溯.然而,使重复回溯(即仅+在主"循环"上)不会导致不匹配,而是导致运行时异常!(如ideone.com上所示):

Exception in thread "main" java.lang.StringIndexOutOfBoundsException:
    String index out of range: -1

    at java.lang.String.charAt(String.java:686) …
Run Code Online (Sandbox Code Playgroud)

java regex fibonacci nested-reference

16
推荐指数
1
解决办法
2135
查看次数

这个正则表达式替换如何反转字符串?

这是一系列教育正则表达式文章的第四部分.它展示了嵌套引用的组合(请参阅:这个正则表达式如何找到三角形数??)在断言中"计数"(参见:我们如何匹配^ nb ^ n与Java正则表达式?)可用于反转字符串.以编程方式生成的模式使用元模式抽象(请参阅:此Java正则表达式如何检测回文?).这是系列中的第一次,这些技术用于替换而不是整个字符串匹配.

提供了完整的Java和C#实现.鼓舞人心的报价包括在内.

使用正则表达式反转字符串似乎不是一个好主意,如果它完全可能,它甚至不会立即显而易见,如果是这样,人们可能会尝试这样做.

虽然它仍然不是一个好主意,但至少现在我们知道这是可能的,因为这是一种方法:

C#(也在ideone.com上)

using System;
using System.Text.RegularExpressions;

public class TwoDollarReversal {    
public static void Main() {
   string REVERSE = 
      @"(?sx) . grab$2"
         .Replace("grab$2",
            ForEachDotBehind(
               AssertSuffix(@"((.) \1?)")
            )
         );
   Console.WriteLine(
      Regex.Replace(
         @"nietsniE treblA --
         hguone llew ti dnatsrednu t'nod uoy ,ylpmis ti nialpxe t'nac uoy fI",

         REVERSE, "$2"
      )
   );
   // If you can't explain it simply, you don't understand it well enough
   // -- …
Run Code Online (Sandbox Code Playgroud)

c# java regex lookaround nested-reference

16
推荐指数
1
解决办法
5748
查看次数