Tcl正则表达式:带有'(',')'字符的模式中非贪婪量词的帮助

时间:2012-08-02 05:38:21

标签: regex tcl

我的模式如下: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 % 

2 个答案:

答案 0 :(得分:4)

你遇到的问题是Tcl的RE引擎是自动理论的,并且不能很好地应对切换贪婪模式。特别地,对于第一近似,情况是字符串中的第一个量词设置整个RE的贪婪。 (事实并非如此,但是当它切换时的规则是非常神秘的。)

如果您没有嵌套括号,可以使用:

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

测试(省略明显的位):

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

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

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

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

答案 1 :(得分: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