我在尝试使用正则表达式验证输入时遇到这个问题。输入应对应于特定的类似编程的规范,该规范由函数、变量(2 种类型)和字符串组成。
这里有一些例子:
&foo
$foo(&bar)
$foo(&bar+$baz)
$foo($bar "baz" qux+$quux(&corge "grault") &garply)
现有类型:
这里的主要问题是我写了一个正则表达式,当然有回避。但是,我需要验证这样一个事实:在最终匹配本身或在其递归中,至少存在 one 第二种类型的变量 - 实际上并非如此。显然,我的正则表达式应该完全匹配输入。
这是我的正则表达式(它使用 PCRE2),后面是它的解释,以及一套供您尝试的测试:
(?:\$\w+(?:\((?<arg>(?R)|(?:\"[^\"]*\")|(?:[^\$\"\&\s\(\)][^\s\(\)]*))(?:(?:\+| )(?&arg))*\))?)|(?<var>\&\w+)
(?: # function or variable and its arguments
\$\w+ # function or variable prefix + name (ex: $test)
(?: # arguments if it's a function
\( # opening parenthesis
(?<arg> # first argument
(?R) # function or variable
|
(?:\"[^\"]*\") # string
|
(?:[^\$\"\&\s\(\)][^\s\(\)]*) # string literal
)
(?: # other arguments if any
(?:\+| ) # separator
(?&arg) # argument
)*
\) # closing parenthesis
)?
)
|
(?<var>\&\w+) # variable prefix + name (ex: &test)
( # function or variable and its arguments
\$\w+ # function or variable prefix + name (ex: $test)
MAYBE ( # arguments if it's a function
\( # opening parenthesis
GROUP <arg> ( # first argument
RECURSIVE # function or variable
OR
\"[^\"]*\" # string
OR
[^\$\"\&\s\(\)][^\s\(\)]* # string literal
)
MAYBE MULTIPLE ( # other arguments if any
\+ OR SPACE # separator
GROUP arg # argument
)
\) # closing parenthesis
)
)
OR
GROUP <var> (\&\w+) # variable prefix + name (ex: &test)
目标是对其进行转换,以验证组
var
在正则表达式或其递归中至少出现一次。
最好的解决方案是
(?R)
在递归中保持组匹配并将它们传递给他的父模式,我将能够检查组var
是否与(?(var)(*ACCEPT)|(*FAIL))
至少匹配一次。
这是我正在思考的简化版本:
(?:\w(?R)|(\d))(?(1)(*ACCEPT)|(*FAIL))
。这个正则表达式仅匹配 1 个数字,但通过“递归匹配保持”,它可以匹配任何后跟数字的字母链。
不过,似乎根本不可能。我没有找到为此的标志或令牌。
$test($test(test &var1 $var2) $test(jean) jean) # should full-match
$test($test(test $var1 $var2) $test(foo) bar) # should not full-match
$test("&test") # should not full-match
$test("foo&test") # should not full-match
$test("&test" &test) # should full-match
&test # should full-match
$test(" &test") # should not full-match
$test # should not full-match
&test(foo) # should not full-match
&test(&foo $bar()) # should not full-match
$test((&test)) # should not full-match
$foo(bar(&baz)) # should not full match
$test(&test &test) # should not full match
$test( &test) # should not full match
$test(&test ) # should not full match
因此,经过搜索,我想出了一个特定于库的解决方案。不是正则表达式,如果您遇到同样的问题,很抱歉!
mrab-regex
(或简称 regex
) 库(而不是 re
,因为它不支持递归正则表达式等)。
并且,这个库作为一种简单的方法来获取重复组的所有成功匹配的列表,即
captures
。我只是在正则表达式匹配后立即使用它来检查正则表达式捕获组 var
是否为空:
for match in my_regex.finditer(cell):
if not match.captures('var'):
continue
...
mrab-regex
库及其处理重复捕获的方法的更多信息。