这可以在没有在 regex 调用中嵌套 regex 调用的情况下完成。我也不赞同带有条件和临时变量的冗长循环。
这项任务需要召唤的英雄是\G
——“继续”元字符。它允许从字符串中的某个位置开始匹配,并从最后一次匹配完成的位置继续匹配。
代码:(演示)
$str = '"hi (text here) and (other text)" come (again) and "(again)", right?';
echo preg_replace(
'~(?:\G(?!^)|"(?=[^"]+"))[^"()]*(?:"(*SKIP)(*FAIL)|\K[()])~',
'\\\$0',
$str
);
输出:
"hi \(text here\) and \(other text\)" come (again) and "\(again\)", right?
细分:(演示)
(?: #start noncapturing group 1
\G(?!^) #continue, do not match from start of string
| #OR
"(?=[^"]+") #match double quote then lookahead for the second double quote
) #end noncapturing group 1
[^"()]* #match zero or more characters not (, ), or "
(?: #start noncapturing group 2
"(*SKIP)(*FAIL) #consume but do not replace
| #OR
\K #forget any previously matched characters
[()] #match an opening or closing parenthesis
) #end noncapturing group 2
当转义字符应被取消其在字符串/模式中的正常含义时,此解决方案不适应边缘场景。