在LaTeX中,表达式'o{a}{b}
表示运算符'o'接受两个参数a和b。LaTeX也接受'o{a}
,在这种情况下将第二个参数视为空字符串。
现在我尝试匹配正则表达式''''o'{(['s'S]*?)'}'{(['s'S]*?)'}
对字符串'o{a}'o{a}{b}
。当整个字符串不匹配时,它会错误地将其视为匹配。(这个字符串的正确解释是子字符串'o{a}{b}
是唯一匹配的。)关键是我需要知道如何告诉PHP,如果有{后面的第一个}以外的东西,那么它不是一个匹配。
我该怎么做呢?
Edit:操作符的实参允许包含符号'
、{
和}
。但是在这种情况下,整个字符串不匹配的原因是因为a}'o{a
中的花括号不符合LaTeX规则(例如{
必须在}
之前),因此a}'o{a
不能作为操作符的参数…
Edit2:另一方面,'o{{a}}{b}
应该是匹配的,因为{a}
是一个有效的参数
我建议这样做:
$s = '''o{a}''o{a}{b}';
echo "$s'n"; # Check string
preg_match('~'''o('{(?>[^{}''']++|(?1)|'''.)+'}){2}~', $s, $match);
print_r($match);
ideone演示 正则表达式:
- 使用递归处理嵌套的大括号,
- 也使用反斜杠(
[^{}''']
和'''.
)来避免使用文本大括号作为语法大括号。
'''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]*?)
,它将尝试寻找即将到来的下一个'}
,并且在那里,无论您是使用懒惰量词还是贪婪量词,都无关紧要。您需要在实际的'}
出现在正则表达式之前以某种方式阻止它匹配}
。
这就是为什么你必须使用[^{}]
,因为你实际上可以在里面嵌套大括号,这是使用递归的理想情况。
要处理可能嵌套的大括号,您需要使用递归特性:
$pattern = <<<'EOD'
~
''o({(?>[^{}]+|(?-1))*}){2}
~x
EOD;
(?-1)
是对最后一个捕获组的子模式的引用。我猜你需要考虑使用锚^
和$
$pattern = '/^''o'{.*'}('{.*'})?$/';
我不知道你认为a
和b
的可接受值是多少,所以你可以在这里用合适的类替换.*
。
允许'0{a}
或'o{a}{b}
格式。如果只匹配'o{a}{b}
,修改如下:
$pattern = '/^''o'{.*'}'{.*'}$/';
根据您上次的编辑,我建议将上述.*
替换为[^{]*
,如其他答案所述。