2017-06-15 96 views
2

我想知道是否可以调用子程序,但不捕获该调用的结果。未捕获子程序

举例来说,假设我想递归匹配和捕获平衡括号{}结构像

{dfsdf {sdfdf {{dfsdf}}} dfsf}

我可以使用这正则表达式:

(^(?'nest'\{(?>[^{}]|(?&nest))*\})) 

第一组是我想要捕获。

但是我的 '鸟巢' 的定义:

(?'nest' ...) 

和我的 '鸟巢' 子程序递归调用:

(?&nest) 

也捕获组。我想通过不捕获这些组来提高我的正则表达式的效率并节省空间。有没有办法做到这一点?

编辑:我预计它不可能不捕获子程序定义,因为它的模式需要被捕获以供其他地方使用。


EDIT2:

我测试这个表达式用的boost ::正则表达式以及记事本+ +正则表达式。他们实际上出现了定义不同的捕获组,这对我来说很奇怪。我觉得他们都默认使用Perl正则表达式。

无论如何,在问这个问题,我有正则表达式:

^\w+\s+[^\s]+\s+(?'header'(?'nest'\{(?>[^{}]|(?&nest))*\}))(?>\s+[^\s]+){5}\s+(?'data'(?>\{(?>[^{}]|(?&nest))*\}))\s+(?'class'(?>\{(?>[^{}]|(?&nest))*\})) 

这是我后来才意识到包含不必要的字符“鸟巢”已经封装。而我现在有:

^\w+\s+[^\s]+\s+(?'nest'\{(?>[^{}]|(?&nest))*\})(?>\s+[^\s]+){5}\s+((?&nest))\s+((?&nest)) 

记事本+ +为我提供了3组拍摄的时候我做了REPLACE语句

\\1: \1 \n \\2: \2 \n 3: \3 \n 4: \4 

它告诉我,“出现1次被换下,接下来发生未找到”。 4:之后替换没有文字,使我相信第4个捕获组不存在。

无论其升压:: regex_match返回与6个位置的对象:

0:对比赛元数据

1:整个匹配

2:整个匹配

3: group1 from notepad ++

4:group2 from notepad ++

5:从记事本++

组3我还在努力使位置1的发送和2


EDIT3

我误解又一块拼图...

boost :: cmatch.m_subs [i]!= boost :: cmatch [i]

我以为他们是平等的。一些调试后,事实证明,索引到对象的操作完全相同的文件说。但是,我错误地假定对象将包含镜像[I]返回什么的boost :: C匹配的结构。看来,升压:: C匹配[I]首先去除具有匹配的==假m_subs所有条目。剩下的条目与boost :: cmatch [i]返回的内容一致。

+0

如果您需要在字符串开头匹配那个'{...}'均衡子字符串,否则无法使用非捕获子例程调用。 –

+0

这有什么理由吗?看起来这个功能会增强正则表达式的功能。 – Derek

+0

我宁愿称之为过早优化。 –

回答

1

任何子程序寄予成结构不会捕获任何

如果你只是想避免任何捕获,它的完成这样的

https://regex101.com/r/aT4TlM/1

注意((DEFINE)?) -

子模式定义构建(?(DEFINE)(?'nest'\{(?>[^{}]|(?&nest))*\}))
可以仅被用来定义函数。在这个组中没有匹配。

^(?&nest)(?(DEFINE)(?'nest'\{(?>[^{}]|(?&nest))*\}))

而且因为你有BOS锚有^它是唯一的方法。
I.e. (?R)不是一个选项。

扩展

^
(?&nest) 

(?(DEFINE) 

     (?'nest'      # (1 start) 
      \{ 
      (?> 
       [^{}] 
      | (?&nest) 
      )* 
      \} 
    )        # (1 end) 
) 

输出

** Grp 0  - (pos 0 , len 29) 
{dfsdf{sdfdf{ {dfsdf} }}dfsf} 
    ** Grp 1 [nest] - NULL 

度量

---------------------------------- 
* Format Metrics 
---------------------------------- 
Atomic Groups  = 1 

Capture Groups  = 1 
     Named  = 1 

Recursions   = 2 

Conditionals  = 1 
     DEFINE  = 1 

Character Classes = 1 
+0

感谢所有的信息,我编辑了我的问题以更好地描述发生了什么。 – Derek

1

子程序调用是递归子模式的机制。正则表达式引擎必须知道什么递归组,这就是为什么它要求无论是它的ID(如果组是编号为)或名称(如果它是一组命名,如你的情况)。 非捕获组切勿店引用这些组模式,因此,你不能引用他们的子程序调用内。

在子程序调用不使用捕获组的唯一方法是使用一个快捷方式整个图案(?R)。但它不是一个选项,当你需要递归模式的部分(在你的情况下,如果你想匹配字符串的开始,只有^后递归图形部分。

+0

感谢您的快速回复。我扩大了我的问题,以反映我有一个更深的误解。 – Derek

+0

@Derek如您所见,即使在DEFINE块中,捕获组也可用于定义子模式。唯一的区别是捕获不会在匹配结果中返回。 **如果您需要对它进行递归处理,您无法避免将模式定义为捕获组,只能避免将其放入匹配结果中。 –

1

重新:EDIT2

此正则表达式^\w+\s+[^\s]+\s+(?'nest'\{(?>[^{}]|(?&nest))*\})(?>\s+[^\s]+){5}\s+((?&nest))\s+((?&nest))

当格式化为只包含3个组时可以看到。

^\w+ \s+ [^\s]+ \s+ 
(?'nest'      # (1 start) 
     \{ 
     (?> 
      [^{}] 
     | (?&nest) 
    )* 
     \} 
)        # (1 end) 
(?> \s+ [^\s]+){5} 
\s+ 
((?&nest))     # (2) 
\s+ 
((?&nest))     # (3) 

你想用这个做什么?

+0

它的工作原理是正确的......我的原始正则表达式是不正确的,但我认为我已经正确地写了它,并且不恰当的分组是基础软件的症状,而不是我的正则表达式。这是由于我在VS2013中调试时出现boost :: cmatch对象的错误解释。 – Derek

+0

是的,它看起来像从文档'sub_match类型的对象只能通过为match_results类型的对象下标来获得。“从match_results [I]获得的sub_match包含获取关于该组的东西的方法。像迭代器first/last(用于string(m [2] .first,m [2] .second)),bools类似匹配,以及其他直接字符串转换,如m [2] .basic_string()。还有位置和长度。 – sln

+0

当我使用sub_match时,有时我会深入到这个层次'(int)_m [i] .first._Ptr',直接与其他长度和位置或特定的不相关偏移进行比较。 – sln