我有一个正则表达式,用于匹配 (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)
等表达式!
现在的问题是:有没有办法引用模式而不是匹配值?!
最佳答案
请注意,\g{N}
等同于 \1
,即匹配相同值的反向引用 ,而不是对应的捕获组匹配的模式。不过,此语法更灵活一些,因为您可以通过在数字前使用 -
来定义与当前组相对的捕获组(即 \g {-2}
,(\p{L})(\d)\g{-2}
将匹配 a1a
)。
PCRE 引擎允许 subroutine calls递归子模式。要重复第 1 组的模式,请使用 (?1)
和 (?&Val)
来递归命名组 Val
的模式。
此外,您可以使用字符类来匹配单个字符,并考虑使用 ?
量词使部分正则表达式可选:
(\(\s*(?P<Val>[a-zA-Z]+[0-9]*|[0-9]+|\'.*\'|\[.*\])\s*(ni|in|[*\/+-]|[=!><]=|[><])\s*((?&Val))\s*\))
参见 regex demo
注意 \'.*\'
和 \[.*\]
可以匹配太多,考虑替换为 \'[^\'] *\'
和 \[[^][]*\]
。
关于php - 匹配不同值的 RegEx BackReference,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38992457/