6

我正在尝试构建一个正则表达式来匹配字符串,例如

1.) $(Something)
2.) $(SomethingElse, ")")
3.) $(SomethingElse, $(SomethingMore), Bla)
4.) $$(NoMatch) <-- should not match
5.) $$$(ShouldMatch) <-- so basically $$ will produce $

在一个文本中。

编辑: Something、SomethingElse、NoMatch、ShouldMatch 甚至可以是其他词——它们是宏的名称。我尝试匹配的字符串是“宏调用”,它可以出现在文本中,应该用它们的结果替换。我只需要正则表达式来突出显示语法。应突出显示完整的宏调用。3 号目前不那么重要。1号和2号需要工作。如果数字 4 和 5 不能像上面写的那样工作,但$(a 之后的任何一个$都不会匹配,这很好。

目前我有

(?<!\$)+\$\(([^)]*)\)

$(如果没有前导,它匹配任何$,如果我找不到另一种应用$$结构的方法,这可能很好。

我想完成的下一步是忽略引号中的右括号。我怎么能做到这一点?

编辑所以如果我有这样的输入

Some text, doesn't matter what. And a $(MyMacro, ")") which will be replaced.

完整的'$(MyMacro, ")")'将突出显示。

我已经有这个表情了

"(?:\\\\|\\"|[^"])*"

对于引号,包括转义引号。但我不知道如何应用它来忽略它们之间的一切......

PS 我正在使用 .NET 来应用正则表达式。因此将支持平衡组。我只是不知道如何应用这一切。

4

5 回答 5

5

您可以使用这样的表达式:

(?<! \$ )                     # not preceded by $
\$ (?: \$\$ )?                # $ or $$$
\(                            # opening (

(?>                           # non-backtracking atomic group
  (?>                         # non-backtracking atomic group
    [^"'()]+                  # literals, spaces, etc
  | " (?: [^"\\]+ | \\. )* "  # double quoted string with escapes
  | ' (?: [^'\\]+ | \\. )* '  # single quoted string with escapes
  | (?<open>       \( )       # open += 1
  | (?<close-open> \) )       # open -= 1, only if open > 0 (balancing group)
  )*
)

(?(open) (?!) )               # fail if open > 0

\)                            # final )

可以引用如上。例如在 C# 中:

var regex = new Regex(@"(?x)    # enable eXtended mode (ignore spaces, comments)
(?<! \$ )                       # not preceded by $
\$ (?: \$\$ )                   # $ or $$$
\(                              # opening (

(?>                             # non-backtracking atomic group
  (?>                           # non-backtracking atomic group
    [^""'()]+                   # literals, spaces, etc
  | "" (?: [^""\\]+ | \\. )* "" # double quoted string with escapes
  | '  (?: [^'\\]+ | \\. )*  '  # single quoted string with escapes
  | (?<open>       \( )         # open += 1
  | (?<close-open> \) )         # open -= 1, only if open > 0 (balancing group)
  )*
)

(?(open) (?!) )                 # fail if open > 0

\)                              # final )
");
于 2013-03-13T18:26:15.677 回答
1

对于将宏作为参数(1和2)的部分,您可以执行以下操作:

(?<!\$)+\$\(([^)]*?("[^"]*?")?)+\)

你可以在这里看到

在宏 (3) 的情况下,您可以执行以下操作:

(?<!\$)+\$\(([^)]*?("[^"]*?")?(\$\([^)]*?\))?)+\)

但这不适用于包含带括号的字符串的宏。

你可以在这里看到结果

于 2013-03-11T16:46:29.837 回答
1

像这样的事情很复杂......所以不要害怕以下内容:

正则表达式:(?<!\$)(?:\$\$)*(\$\((?:[\w, ]+|(?>"(?:(?<=\\)"|[^"])+")|(?1)+)*\))
在这里解释演示:http ://regex101.com/r/yZ5dI7

这遵循您的所有 5 点,仅当前缀的数量为奇数 时,才会匹配前 3 种宏类型,甚至更深层次的变化与多个"或宏内部宏。$

于 2013-03-11T20:32:28.937 回答
0

我最近在寻找类似的正则表达式,但我决定用 C# 解析文本比正则表达式更快,因为我的正则表达式技能不好......所以我写了这个方法来删除 Razor 代码块。

您可以轻松修改它以满足您的需求,而无需复杂的正则表达式

于 2013-03-06T16:47:00.757 回答
0

你的意思是这样的?

\$\(SomethingElse, \"|[^"\)]?\"\)
于 2013-03-06T16:56:50.713 回答