【问题标题】:C# Regex search for dotted functions and their argumentsC# 正则表达式搜索点函数及其参数
【发布时间】:2017-01-26 18:35:56
【问题描述】:

我需要在文本字符串中搜索所有出现的链式 C# 类函数。例如,我想分解每个方法及其括号中的参数,例如:

object.method(1, "2", abc).method2().method3("test(), 1, 2, 3").method4("\"Hi\"")

这是我几乎可以使用的正则表达式模式:

(?<objectName>[^\}]*?)\.(?<methodName>[^\}]*?)\(((?:[^;"']|"[^"]*"|'[^']*')+)*?\)

这会正确提取objectName和第一个methodName,但是会卡住

1, "2", abc).method2().method3("test, 1, 2, 3").method4("\"Hi\""

全部放入第三个参数为“$1”。

我最新的方法是通过删除 objectName 规范来分而治之,因为它很容易解析出来。这导致我使用:

\.(?<methodName>[^(]*?)\(((?:[^;"']|"[^"]*"|'[^']*')+)*?\)

显然没有objectName,这会产生与以前相似的结果。我这样做是为了查看是否可以获得全局结果,但是否可以获得正确的正则表达式语法。

总之,我需要将多个链接的 .method(parameters) 事件解析为它们名为“methodName”和“parameters”的组成部分。我已经推断出一些事情,但我的正则表达式技能充其量是相当生疏,目前无法克服这一点。感谢您提供的任何帮助。

我一直在使用这个网站进行测试:http://regexstorm.net/tester

更新:为了澄清,要求不包括支持 C# lambda 表达式,只包括点函数语法。这不是一个完整的 C# 解析器。唯一需要的是点方法链接。对于任何混淆,我深表歉意。我想要突破的模式是:

object.method(arguments).method(arguments).method(arguments)...

我的方法是首先提取对象名称,这是一个不需要使用正则表达式的简单操作。现在,这会将正则表达式解析为以下两个组成部分:

.method(arguments).method(arguments).method(arguments)...

这会产生:

method   arguments
method   arguments
method   arguments
...

arguments 可能为 null(缺失),如 .method(),或者方法实际上可能是一个属性(无括号和参数),如:

.method.method().method(arguments)

这会产生:

method   (null)
method   (string.Empty)
method   arguments

arguments 将包含左括号和右括号之间的所有内容;目前不需要解析这些,因为它们将在后续的 Regex 操作中进行处理。

在我看来,这似乎在 Regex 的能力范围内,可以检测 dot-method-openPar-argumentsStr-closePar 下一个 dot-method-openPar-argumentsStr-closePar 等简单模式。

这是语法的范围 - 没有 cmets,没有 lambda - 只是 object.method(arguments).method()...

我希望这会有所帮助。

【问题讨论】:

  • 每个 () 按“(”的顺序创建一个组。您是否尝试过使用较高的 $ 像“$2”或“$3”来查看它们是否包含所需的输出?
  • 当我向您介绍这条链时,您的希望将破灭:'method1(").ToString()").method2(1).method3(").Fail()")'
  • 前段时间我回答了一个非常相似的question。正则表达式将非常大。

标签: c# .net regex vb.net


【解决方案1】:

这不能通过正则表达式正确完成,因为您的参数太不可预测,并且正则表达式语法水平无法与 C# 解析器语法相提并论。例如,它可以包含任何内容的字符串:

method1("x.hiThere().lol()").method2()

它可以嵌套:

method1(x=>method2().method3())

它可以这样做:

a("b().c()",d=> d(").hi()"))

对于您的问题解决方案,您需要了解Grammars,并为此特定任务编写 C# 语法。框架方面可以从ANTLR项目开始。

说明

因为你不能这样做的原因是语法类型差异。 正则表达式使用常规语言,在乔姆斯基层次结构中是 Type-3。 C# 使用上下文无关语言,在 Chomsky 层次结构中是 Type-2

如果你直观地表示它,C# 是比 Regex 语言更强大的语言:

例如,你的情况落入解析器的坑只是因为C#中的lambda:

method1(x=>
{
    ....
    /* some code here */
    ....
}).method2()

【讨论】:

  • 我支持你,这不应该使用正则表达式来解决,但发布的问题可以handle
  • 我创建这个答案的案例是基本的。 Regex 语法是 Type-3 语法(Regular),另一方面是 C# 语法 - Type-2 语法(Context-free)。这意味着Regex语法总是不能代表C#语法的情况。
  • 感谢@ecron06。关于解析科学的优秀信息。我已经更新了原始帖子以限制问题的范围。 C# 参考仅用于说明问题的框架。非常感谢您的回答。
  • 鉴于明确的有限范围,还有其他人有其他想法/想法吗?
猜你喜欢
  • 1970-01-01
  • 2011-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多