【问题标题】:Is it possible to convert PHP Regex (using subroutine calls) to C# regex?是否可以将 PHP 正则表达式(使用子例程调用)转换为 C# 正则表达式?
【发布时间】:2017-11-12 08:06:22
【问题描述】:

示例 php 正则表达式(如下)使用子例程调用来工作。

如果我尝试将它与 C# Regex 类一起使用,我会收到错误:Unrecognized grouping construct

是否可以将其重写为 C# 正则表达式语法?

是简单的翻译,还是需要使用其他(正则表达式)方法?

如果不可能,它正在使用的东西的名称是什么,所以我可以将它添加到这个问题中,以使其对其他有同样问题的人更有用?

适用于所有 json RFC 测试数据的 PHP

$pcre_regex = '
  /
  (?(DEFINE)
     (?<number>   -? (?: [1-9]\d*| 0 ) (\.\d+)? (e [+-]? \d+)? )    
     (?<boolean>   true | false | null )
     (?<string>    " (?>[^"\\\\]+ | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* " )
     (?<array>     \[  (?:  (?&json)  (?: , (?&json)  )*  )?  \s* \] )
     (?<pair>      \s* (?&string) \s* : (?&json)  )
     (?<object>    \{  (?:  (?&pair)  (?: , (?&pair)  )*  )?  \s* \} )
     (?<json>   \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) \s* )
  )
  \A (?&json) \z
  /six   
';

并且不能在 C# 中工作

string pattern = @"(?(DEFINE)
 (?<number>   -? (?: [1-9]\d* | 0 ) (\.\d+)? (e [+-]? \d+)? )    
 (?<boolean>   true | false | null )
 (?<string>    "" (?>[^""\\\\]+ | \\\\ [""\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* "" )
 (?<array>     \[  (?:  (?&json)  (?: , (?&json)  )*  )?  \s* \] )
 (?<pair>      \s* (?&string) \s* : (?&json)  )
 (?<object>    \{  (?:  (?&pair)  (?: , (?&pair)  )*  )?  \s* \} )
 (?<json>   \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) \s* ))
\A (?&json) \z
";
    string input = @"[{\"Example\": \"data\"}]";
    RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline;

    bool isValid = Regex.IsMatch(input, pattern, options);

编辑:这个问题不是关于在 json 中使用正则表达式,而是关于如何在 C# 中做某事(子例程调用),这可以在 PHP 正则表达式中完成

仅仅因为在 C# 中有一种解析 json 的方法回答了这个问题。请保持你的答案和主题。

【问题讨论】:

  • 您应该在 html 中使用正则表达式。 html 不是常规的,而正则表达式用于常规文本。在类中使用 html 类和方法。
  • 当您简化正则表达式以查找引发错误消息的构造时,您发现了什么?请阅读minimal reproducible example 和其他help center 页面。
  • FWIW json 足够规则,可以与(某些)现代正则表达式引擎一起使用请参阅:stackoverflow.com/a/3845829/309634
  • 不可能使用单个正则表达式,因为递归是不可能的。即使使用平衡组也不能提供递归的所有功能。我能够创建一个 99% 的正则表达式,但它不能做的是匹配数组内的嵌套对象,因为它不能递归子组(数组)中的父组(对象)
  • @DarcyThomas:好的,关于“数字”子模式,使用前瞻测试是愚蠢的,因为您可以直接匹配数字的开头。此外,由于整个模式不区分大小写,因此无需编写:[eE]。关于“字符串”子模式,如果您想获得灾难性回溯(例如带有不带右引号的字符串)。结束 \Z 是一行的结尾,\z 是字符串的结尾。

标签: c# php regex


【解决方案1】:

这并不能直接回答问题,而是一种解决方法。

没有使用 BCL Regex 类,有一个名为 PCRE.NET 的项目,它用 C# 函数调用包装了 PCRE 正则表达式引擎(与 PHP 示例中使用的引擎相同)。

这将允许在 C# 领域中将正则表达式与子例程调用一起使用。

【讨论】:

  • 很高兴您发现我的 lib 很有用 :) 要回答最初的问题:,没有通用方法可以将递归 PCRE 模式转换为 . NET 正则表达式。这两个正则表达式引擎在几个方面根本不同,并且每个引擎都支持另一个不支持的某些功能。这就是我最初编写库的动机。有时您可以通过平衡组来解决 .NET 正则表达式中缺少递归的问题,但是一旦您拥有不同类型的组,您很可能不走运,或者您将不得不编写一个可怕的模式。
  • 请参阅 herehere 了解与您的问题相关的一些非常好的信息(由 Kobi 提供)。
【解决方案2】:

简短的回答是有点,但不是真的。

.Net 正则表达式有一个叫做平衡组的概念。

这对于检查所有左大括号是否匹配(即嵌套可以,但重叠不行)非常有用

例如,这个正则表达式将确保所有的花括号都匹配:

{(?:[^{}]|(?&lt;Open&gt;{)|(?&lt;Content-Open&gt;}))+(?(Open)(?!))}

匹配这个字符串:

{1 2 {3} {4 5 {6}} 7}

但是,我无法制作一个包含多个嵌套分组的正则表达式;就像在示例中一样。

更重要的是looks like,您需要创建一个嵌套的正则表达式模式,其中包含您在源数据中期望的尽可能多的嵌套。

您可以尝试将平衡组与一些递归 C# 相结合,以减少每个分组。这个answer 有类似的东西(但在这种情况下我不会推荐它)

或者,您可以添加 this nuget 包。它是 PCRE 正则表达式引擎的包装器,它支持递归子例程。详情here

【讨论】:

    猜你喜欢
    • 2016-04-02
    • 2013-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-02
    相关资源
    最近更新 更多