我有一个正则表达式,用于匹配表单的表达式 (val1 operator val2)
这个正则表达式看起来像:
(\(\s*([a-zA-Z]+[0-9]*|[0-9]+|\'.*\'|\[.*\])\s*(ni|in|\*|\/|\+|\-|==|!=|>|>=|<|<=)\s*([a-zA-Z]+[0-9]*|[0-9]+|\'.*\'|\[.*\])\s*\))
Run Code Online (Sandbox Code Playgroud)
但是:D(黄油来了)
我想通过使其更具可读性和“紧凑”来优化正则表达式本身。我搜索了如何做到这一点,我发现了一种叫做反向引用的东西,你可以在其中命名你的捕获组,然后稍后引用它们:
(\(\s*(?P<Val>[a-zA-Z]+[0-9]*|[0-9]+|\'.*\'|\[.*\])\s*(ni|in|\*|\/|\+|\-|==|!=|>|>=|<|<=)\s*(\g{Val})\s*\))
Run Code Online (Sandbox Code Playgroud)
我将捕获表达式左侧的组命名为 ,然后将其Val引用为(\g{Val}),现在的问题是,您在这里看到的这个表达式仅在表达式左侧与右侧完全相同的情况下!例如(a==a)or (1==1)and 不匹配诸如(a==b)! 之类的表达式。
现在的问题是:有没有办法引用模式而不是匹配的值?!
请注意,这\g{N}等效于\1,即匹配相同值的反向引用,而不是匹配相应捕获组匹配的模式。不过,这种语法更灵活一些,因为您可以通过在数字之前使用来定义与当前组相关的捕获组(即,将匹配)。-\g{-2}(\p{L})(\d)\g{-2}a1a
PCRE 引擎允许子程序调用递归子模式。要重复第 1 组的模式,请使用(?1)和(?&Val)递归命名组的模式Val。
此外,您可以使用字符类来匹配单个字符,并考虑使用?量词使正则表达式的一部分成为可选的:
(\(\s*(?P<Val>[a-zA-Z]+[0-9]*|[0-9]+|\'.*\'|\[.*\])\s*(ni|in|[*\/+-]|[=!><]=|[><])\s*((?&Val))\s*\))
Run Code Online (Sandbox Code Playgroud)
查看正则表达式演示
注意\'.*\'and\[.*\]可以匹配太多,考虑用\'[^\']*\'and替换\[[^][]*\]。