这是关于正则表达式的下一个问题。 老实说,我想为数学乘法建立动画,当他们输入一些公式时,他们会得到动画来描述这个数字将在哪里计算,这部分是我的代码。
$pattern = '([*])';
$replace = '||';
$stringAsli = (123*1.23*(0.12/8))*(123*512+40);
$replaceResult= str_replace($pattern,$replace,$stringAsli);
但我得到了结果:
(123||1.23||(0.12/8))||(123||512+40)
我想要这样的结果
(123||1.23||(0.12/8))*(123||512+40);
扩展要求
在带引号字符串的特殊情况下:
("123*1.23*n"*"(0.12/8)")*("123*512"+40)
应该成为
("123||1.23||n"$"(0.12/8)")*("123||512"+40)
换句话说,仍然会替换括号内的*
,但如果我们在引用的字符串中替换为||
,如果不是,则替换为$
答案 0 :(得分:3)
为了安全地进入括号,我们需要使用递归正则表达式。幸运的是,PHP支持这一点。这样做(参见在线演示的输出):
$mystring = "(123*1.23*(0.12/8))*(123*512+40)";
$nested_parentheses_regex="~\((?:[^()]++|(?R))*\)~";
$replaced = preg_replace_callback(
$nested_parentheses_regex,
function($m) { return str_replace("*","||",$m[0]);},
$mystring
);
echo $replaced;
查看the online demo的输出。
<强>解释强>
\((?:[^()]++|(?R))*\)
匹配(可能)嵌套括号preg_replace_callback
函数调用一个匿名函数,该函数用匹配中的*
替换每个||
(这是一组嵌套括号。您现在在括号内询问,当星号不在引号内时,我们返回$
使用此:
$mystring = '("123*1.23*n"*"(0.12/8)")*("123*512"+40)';
$nested_parentheses_regex ="~\((?:[^()]++|(?R))*\)~";
$replaced = preg_replace_callback($nested_parentheses_regex,
function($m) {
return preg_replace_callback(
'~"[^"]*"|(\*)~', // complete "quote" OR capture * to Group 1
function($n) {
// Not inside quotes?
if(isset($n[1])) return "\$";
else { // we matched a "full quote"
return str_replace("*","||",$n[0]);
}
},
$m[0] // this is a (full (set) of parentheses)
); // end inner callback
},
$mystring
); // end outer callback
echo $replaced;
答案 1 :(得分:2)
为了好玩,实施了一个无正则表达式的解决方案:
它可能比正则表达式更快;-D
$str = '(123*1.23*(0.12/8))*(123*512+40)';
$depth = 0;
for ($i = 0; $i < strlen($str); ++$i) {
$char = $str[$i];
switch ($char) {
case '(':
++$depth;
break;
case ')':
--$depth;
break;
case '*':
if ($depth != 0) {
$str = substr_replace($str, '||', $i, 1);
++$i;
}
break;
}
}
echo $str;
答案 2 :(得分:1)
如果您尝试仅替换括号内的文字*
,那将会变得棘手且需要递归的正则表达式模式。
嵌套括号的递归正则表达式模式类似于\((?>(?>[^()]+)|(?R))*\)
。
\( # matches a literal (
(?> # starts an atomic group
(?> # starts an atomic group
[^()]+ # matches 1 or more characters that are not parenthesis
) # ends atomic group
| # allows an alternative pattern
(?R) # allows the pattern to be recursed
) # ends atomic group
* # signifies the pattern match 0 or more times
\) # matches a literal )
该模式将允许您获取括号内所有内容的所有匹配。
$pattern = '/\((?>(?>[^()]+)|(?R))*\)/';
$subject = '(123*1.23*(0.12/8))*(123*512+40)';
$replacements = $matches = array();
preg_match_all($pattern, $subject, $matches);
为了对所有这些组进行额外的替换,我决定创建一个文字替换对的数组。
foreach($matches[0] as $match) {
$replacements[$match] = preg_replace('/[*]/', '||', $match);
}
这为您提供了$replacements
中的数组,其中包含要替换的内容的键以及替换内容的值,您可以在str_replace
中使用它来对应原始字符串。
$result = str_replace(array_keys($replacements), array_values($replacements), $subject);