我有一个正则表达式,用于匹配表单(val1 operator val2)
这个正则表达式看起来像:
(\(\s*([a-zA-Z]+[0-9]*|[0-9]+|\'.*\'|\[.*\])\s*(ni|in|\*|\/|\+|\-|==|!=|>|>=|<|<=)\s*([a-zA-Z]+[0-9]*|[0-9]+|\'.*\'|\[.*\])\s*\))
这实际上很好并且符合我的要求here in this demo
但是:D(这是黄油)
我希望通过使其更具可读性和“紧凑”来优化正则表达式本身。我搜索了如何做到这一点,我找到了一个叫做反向引用的东西,你可以在其中命名你的捕获组,然后再引用它们:
(\(\s*(?P<Val>[a-zA-Z]+[0-9]*|[0-9]+|\'.*\'|\[.*\])\s*(ni|in|\*|\/|\+|\-|==|!=|>|>=|<|<=)\s*(\g{Val})\s*\))
我在那里命名了捕获表达式Val
左侧的组,后来我将其引用为(\g{Val})
,现在问题就是这个表达式,你可以仅看here表达式左侧与右侧完全相同的情况!例如(a==a)
或(1==1)
,与(a==b)
!
现在的问题是:有没有办法引用模式而不是匹配的值?!
答案 0 :(得分:3)
请注意,\g{N}
相当于\1
,即反向引用,它匹配相同的值,而不是模式,相应的捕获组匹配。此语法稍微灵活一些,因为您可以在数字前使用-
来定义 relative 到当前组的捕获组(即\g{-2}
,{{ 1}}将匹配(\p{L})(\d)\g{-2}
)。
PCRE引擎允许subroutine calls递归子模式。要重复第1组的模式,请使用a1a
和(?1)
来递归命名组(?&Val)
的模式。
此外,您可以使用字符类来匹配单个字符,并考虑使用Val
量词来使正则表达式的部分可选:
?
请参阅regex demo
请注意(\(\s*(?P<Val>[a-zA-Z]+[0-9]*|[0-9]+|\'.*\'|\[.*\])\s*(ni|in|[*\/+-]|[=!><]=|[><])\s*((?&Val))\s*\))
和\'.*\'
匹配过多,请考虑替换为\[.*\]
和\'[^\']*\'
。
答案 1 :(得分:1)
您使用此正则表达式的语言/应用程序是什么? 如果您有选项,则可以将不同的部分指定为命名变量,然后通过组合它们来构建最终的正则表达式。
val = "([a-zA-Z]+[0-9]*|[0-9]+|\'.*\'|\[.*\])"
op = "(ni|in|\*|\/|\+|\-|==|!=|>|>=|<|<=)"
exp = "(\(" .. val .. "\s*" .. op .. "\s*" .. val .. "\))"