2

我有这样的模式: substring1(substring2),(xxxx)xxxx 需要substring1(第一个括号前的字符串)和substring2(第一个括号内的字符串),这没问题。此外,需要一个子字符串中第一个括号后的所有字符 - 这些可能是括号本身。因此使用模式 -regexp {(.*?)\((.*?)\)(.*)} $a match sub1 sub2 sub3 但最后一个子字符串不能收集在sub3. 请帮我!

> 247 % set a substring1(substring2),(xxxx)xxxx
> 248 % regexp {(.*?)\((.*?)\)(.*)} $a match sub1 sub2 sub3 1
> 249 % puts $sub1; puts $sub2; puts $sub3 
substring1
substring2

> 250 % 
4

2 回答 2

4

你遇到的问题是 Tcl 的 RE 引擎是自动机理论的,不能很好地处理切换贪婪模式。特别是,对于第一个近似值,字符串中的第一个量词设置整个 RE 的贪心度。(这实际上不是真的,但它何时切换的规则非常神秘。)

如果你没有嵌套括号,你可以使用这个:

regexp {^([^()]*)\(([^()]*)\)(.*)$} $a match sub1 sub2 sub3

测试(省略了明显的位):

% puts $sub1|$sub2|$sub3
substring1|substring2|,(xxxx)xxxx

处理嵌套括号要困难得多。问题在于,任意嵌套是您不再处理可以由有限自动机正式匹配的“语言”的地方(相反,您需要一个下推自动机,这是一个不同的可判定性类)。对于有限级别的嵌套,您可以对其进行编码;以下是如何在一个级别上做到这一点:

regexp {^([^(]*)\(((?:[^()]|\([^()]*\))*)\)(.*)$} $a match sub1 sub2 sub3

也就是说,我[^()](?:[^()]|\([^()]*\)). [^()]您可以根据需要再次替换第二个 sub- 来轻松深入。然而,这使得 RE 更加复杂(这实际上是问题所在;任意嵌套的 paren 匹配器将需要无限长的 RE)。如果您正在处理该特定问题,尝试找到一些其他技术会更容易(例如,更长的“块结尾”字符串以匹配),- 与逗号 - 或使用递归解析器)。

于 2012-08-02T09:52:04.143 回答
1

需要以匹配终止,直到结束变量'$'

 () 27 % regexp {(.*?)\((.*?)\)(.*).*$} $a match sub1 sub2 sub3
 1
 () 28 % set sub3
 ,(xxxx)xxxx
 () 29 % set sub1
 substring1
 () 30 % set sub2
 substring2
 () 31 % set sub3
 ,(xxxx)xxxx
于 2016-01-27T08:32:27.720 回答