在LaTeX中,表达式\o{a}{b}
表示运算符'o'接受两个参数a和b。 LaTeX也接受\o{a}
,在这种情况下,将第二个参数视为空字符串。
现在我尝试将正则表达式\\\\o\{([\s\S]*?)\}\{([\s\S]*?)\}
与字符串\o{a}\o{a}{b}
匹配。它错误地将整个字符串作为匹配而不是。 (对这个字符串的正确解释是子字符串\o{a}{b}
是唯一的匹配。)关键是我需要知道如何告诉PHP如果还有其他东西而不是{跟随第一个},那么它不是匹配。
我该怎么做?
修改:允许运算符的参数包含符号\
,{
和}
。但在这种情况下,整个字符串不匹配的原因是因为a}\o{a
中的大括号不符合LaTeX规则(例如{
必须在}
之前),所以{ {1}}不能是运算符的参数......
Edit2 :另一方面,a}\o{a
应匹配,因为\o{{a}}{b}
是有效参数。
答案 0 :(得分:2)
我建议这样的事情:
$s = '\\o{a}\\o{a}{b}';
echo "$s\n"; # Check string
preg_match('~\\\o(\{(?>[^{}\\\]++|(?1)|\\\.)+\}){2}~', $s, $match);
print_r($match);
正则表达式:
[^{}\\\]
和\\\.
)来避免使用语法大括号的字面括号。\\\o # Matches \o
( # Recursive group to be
\{ # Matches {
(?> # Begin atomic group (just a group that makes the regex faster)
[^{}\\\]++ # Any characteres except braces and backslash
|
(?1) # Or recurse the outer group
|
\\\. # Or match an escaped character
)+ # As many times as necessary
\} # Closing brace
){2} # Repeat twice
当前正则表达式的问题在于,一旦此部分与\\\\o\{([\s\S]*?)
匹配,它将尝试查找即将发生的下一个\}
,并且重要的是,您是否使用了懒惰量词或贪婪的。在真正的}
进入正则表达式之前,您需要以某种方式阻止它与\}
匹配。
这就是为什么你必须使用[^{}]
,因为你实际上可以在里面嵌套括号,这是使用递归的理想情况。
答案 1 :(得分:1)
要处理可能的嵌套花括号,需要使用递归功能:
$pattern = <<<'EOD'
~
\\o({(?>[^{}]+|(?-1))*}){2}
~x
EOD;
其中(?-1)
是对最后一个捕获组的子模式的引用。
答案 2 :(得分:0)
我猜您需要考虑使用锚点^
和$
$pattern = '/^\\o\{.*\}(\{.*\})?$/';
我不知道您认为a
和b
的值是什么值,因此您可以在此处用适当的类替换.*
。
这允许\0{a}
或\o{a}{b}
格式。仅匹配\o{a}{b}
修改:
$pattern = '/^\\o\{.*\}\{.*\}$/';
根据您的上一次修改,我建议将上面的.*
替换为[^{]*
,如其他答案中所述。