我正在使用商业闭源Java应用程序,除了它所做的一切之外,还允许通过提供正则表达式模式字符串来过滤文本字段。我正在广泛使用该过滤器功能。
我遇到的问题是我经常发现自己在正则表达式中重复了相同的子模式。例如,这里
^(
( # pattern foo
foo_([^_]+)_(windows|linux|osx)
)
|
( # pattern bar
([^_]+)_bar_(windows|linux|osx)_foo_(windows|linux|osx)
)
)$
([^_]+)
和(windows|linux|osx)
部分经常重复。
这只是一个例子。原始的正则表达式更复杂,大约20倍,并且有很多不同的重复。它变得有点难以阅读,因为重复的子模式只会在数量和数量上不断增长,而且当你尝试修改重复的子模式时,你也必须修改它的所有重复,这很麻烦。
所以,我玩regex101并想出了这个
^(
( # a dummy option, defines some frequently used capture groups
(?!x)x # always false, so nothing matches this and the following groups ever
(?'name'[^_]+) # group "name"
(?'os'windows|linux|osx) # group "os"
)
|
( # pattern foo
foo_\g'name'_\g'os'
)
|
( # pattern bar
\g'name'_bar_\g'os'_foo_\g'os'
)
)$
现在所有子模式都已命名,每当我引用该名称时,它们都会被子模式字符串替换(即\g'os'
被(windows|linux|osx)
替换)。名称比相应的子模式短很多,它们也很清楚,你必须修改一个子模式,修改才能在正则表达式的任何地方应用。
这个改进版本的问题是虽然它是一个有效的PHP pcre正则表达式,但它是无效的Java正则表达式。除了Comparison to Perl 5中所述,Java不支持\g
中的注释和细则。
有没有什么方法可以“重复”像Java Regex中那样重复的正则表达式模式?不要忘记我所能做的只是提供一个模式字符串,我无法访问代码。