这是我的代码:
str = str.replace(/(\+?(?:(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?|Infinity))([%!]+)/g, function(m, $1, $2) {
return "(" + $1 + ")" + $2.replace(/%/g, ".percent()")
.replace(/!/g, ".fact()");
});
str = str.replace(/([+]?(?:(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?|Infinity)|\)|\%|\!)\^([-+]?(?:(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?|Infinity)|\()/g, function(m, $1, $2) {
if ($1 == ")" && $2 == "(") {
return (").pow(");
}
if ($1 == "%" && $2 == "(") {
return ("%.pow(");
}
if ($1 == "!" && $2 == "(") {
return ("!.pow(");
}
if ($1 == ")") {
return (").pow(" + $2 + ")");
}
if ($1 == "%") {
return ("%.pow(" + $2 + ")");
}
if ($1 == "!") {
return ("!.pow(" + $2 + ")");
}
if ($2 == "(") {
return ("(" + $1 + ").pow(");
}
return ("(" + $1 + ").pow(" + $2 + ")");
});
问题在于我想要替换所有不会发生的事件。
"2%" -> "(2).percent()", working
"2%%" -> "(2).percent()%", should be "(2).percent().percent()"
我使用g修饰符,所以我看不出问题是什么,我该如何解决?
答案 0 :(得分:6)
问题是您的模式与某个数字匹配,"Infinity"
或)
,后跟%
,但第二个%
不在前面其中任何一个,所以它根本就不匹配。
看起来您希望通过在百分比之前匹配)
符号,它将从您之前的替换中获得结束)
,并将其用作下一场比赛的一部分。正则表达式引擎并不像那样工作。找到匹配后,它会继续进行下一场比赛。
换句话说,g
修饰符并不意味着递归替换替换,直到找不到匹配为止,这意味着,'替换原始匹配项中找到的每个匹配项字符串'
我确定还有其他解决方案,但你可以试试这个:
str = str.replace(/(\+?(?:(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?|Infinity))(%+)/g, function(m, $1, $2) {
return "(" + $1 + ")" + new Array($2.length + 1).join(".percent()");
});
鉴于您的更新问题,您可以执行以下操作:
str = str.replace(/(\+?(?:(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?|Infinity))([%!]+)/g, function(m, $1, $2) {
return "(" + $1 + ")" + $2.replace(/%/g, ".percent()")
.replace(/!/g, ".fact()");
});
鉴于您的第二次更新:
var re = /(\+?(?:(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?|Infinity))((?:[%!]|\^[+-]?(?:(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?|Infinity|\())*)/g;
str = str.replace(
re,
function(m, $1, $2) {
return "(" + $1 + ")" + $2.replace(/\^([^(^%!]+)/g, ".pow($1)")
.replace(/\^\(/g, ".pow(")
.replace(/%/g, ".percent()")
.replace(/!/g, ".fact()");
});
$('#go').click(function() {
var str = $("#input").val();
var re = /(\+?(?:(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?|Infinity))((?:[%!]|\^[+-]?(?:(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?|Infinity|\())*)/g;
str = str.replace(
re,
function(m, $1, $2) {
return "(" + $1 + ")" + $2.replace(/\^([^(^%!]+)/g, ".pow($1)")
.replace(/\^\(/g, ".pow(")
.replace(/%/g, ".percent()")
.replace(/!/g, ".fact()");
});
$("#output").text(str);
});

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="input" value="5!^3%" /><button id="go">Go</button>
<div id="output" />
&#13;
但是,在你走得更远之前我会提醒你。看起来这个问题最好用一个合适的解析器解决。查看jison以获取有助于构建解析器的良好资源。
我支持我之前关于正则表达式的有用性有限的警告,但这可能是一种更简单的方法,只要您确定输入的一般格式大致正确,你不要介意一些不必要的括号:
str = str.replace(/[+-]?(?:(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?|Infinity)/g, "($&)")
.replace(/%/g, ".percent()")
.replace(/!/g, ".fact()")
.replace(/\^/g, ".pow");
$('#go').click(function() {
var str = $("#input").val();
str = str.replace(/[+-]?(?:(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?|Infinity)/g, "($&)")
.replace(/%/g, ".percent()")
.replace(/!/g, ".fact()")
.replace(/\^/g, ".pow");
$("#output").text(str);
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="input" value="(2)^2!" /><button id="go">Go</button>
<div id="output" />
&#13;