This question already has an answer here:
这个问题已经有了答案:
- Why does a RegExp with global flag give wrong results? 6 answers
- 为什么带有全球标志的RegExp会产生错误的结果?6答案
这是一个代码页版本。
My goal is to iterate over the elements of an array, search for a regex matching ~@
something@~
, remove those "bookends" identifying the match, then .join()
the array. In the following example, the result should look like a/b/c
.
我的目标是遍历数组的元素,搜索regex匹配~@something@~,删除标识匹配的“bookends”,然后删除.join()数组。在下面的示例中,结果应该类似于a/b/c。
However instead, I get the result a/~@b@~/c
. To make things even more confusing, when I reverse the order of the array elements, the problem result changes from the ~@b@~
to the ~@c@~
. And, finally, to make things downright weird, the problem seems to resolve itself by adding a simple test
method which, itself, always returns a value of false
. See comments for those in code. And see for yourself.
但是,我得到的结果是a/~@b@~/c。更让人困惑的是,当我反转数组元素的顺序时,问题的结果从~@b@~变成~@c@~。最后,为了让事情变得完全怪异,问题似乎是通过添加一个简单的测试方法来解决的,这个方法本身总是返回一个false值。请参阅代码中的注释。看看你自己。
What is causing this strange behavior? And what is the correct way to iterate over these elements and do the substitution I describe?
是什么导致了这种奇怪的行为?迭代这些元素并做我描述的替换的正确方法是什么?
function myFunction() {
var a = ["a", "~@b@~", "~@c@~"]
var re = /~@(.*?)@~/g;
var i = a.length;
// Uncomment below line to see the problem change from ~@b@~ to ~@c@~
//a.reverse();
while (i--) {
console.log('i', i, 'str', a[i]);
var match = re.exec(a[i]);
console.log('match', match);
// Uncomment the below line to see it work properly.
//console.log('test', re.test(a[i]));
if (match && match[0] && match[1]) {
a[i] = a[i].replace(match[0], match[1]);
console.log('a[i]', a[i]);
}
}
var res = a.join('/');
document.getElementById("demo").innerHTML = res;
}
<p>
My goal is to print the string: <code>a/b/c</code>. See weird <i>uncomment</i> fix in JS.
<button onclick="myFunction()">Click Here</button>
</p>
<p id="demo"></p>
2 个解决方案
#1
2
The reason for the behavior is that your regex has the global flag (g
) but you're only executing it once; that means its lastIndex
is set and the next time you run it, it tries to start from where it left off.
这种行为的原因是您的regex有全局标志(g),但是您只执行一次;这意味着设置了它的lastIndex,下次运行它时,它试图从它停止的地方开始。
Either remove the g
flag, or add
要么删除g标志,要么添加。
re.lastIndex = -1;
...as the first line in the while
loop:
…作为while循环的第一行:
function myFunction() {
var a = ["a", "~@b@~", "~@c@~"]
var re = /~@(.*?)@~/; // <=== Note `g` removed
var i = a.length;
var t;
while (i--) {
var match = re.exec(a[i]);
if (match && match[0] && match[1]) {
a[i] = a[i].replace(match[0], match[1]);
}
}
var res = a.join('/');
document.getElementById("demo").innerHTML = res;
}
<p>
My goal is to print the string: <code>a/b/c</code>. See weird <i>uncomment</i> fix in JS.
<button onclick="myFunction()">Click Here</button>
</p>
<p id="demo"></p>
However, if you leave that g
flag on the regex, you can replace the entire contents of the while
loop with
但是,如果在regex中保留g标志,则可以将while循环的全部内容替换为
a[i] = a[i].replace(re, "$1");
function myFunction() {
var a = ["a", "~@b@~", "~@c@~"]
var re = /~@(.*?)@~/;
var i = a.length;
var t;
// Uncomment below line to see the problem change from ~@b@~ to ~@c@~
//a.reverse();
while (i--) {
a[i] = a[i].replace(re, "$1");
}
var res = a.join('/');
document.getElementById("demo").innerHTML = res;
}
<p>
My goal is to print the string: <code>a/b/c</code>. See weird <i>uncomment</i> fix in JS.
<button onclick="myFunction()">Click Here</button>
</p>
<p id="demo"></p>
...which also has the advantage of handling entries in the form "~@b@~~@c@~"
(because it replaces all occurrences in the string, not just the first one).
…它还具有处理形式为“~@b@~~@c@~”的条目的优势(因为它替换了字符串中的所有事件,而不仅仅是第一个)。
#2
1
Removing the global flag from the regex to change from:
从正则表达式中移除全局标志以更改:
var re = /~@(.*?)@~/g;
to:
:
var re = /~@(.*?)@~/;
should fix this.
应该解决这个问题。
#1
2
The reason for the behavior is that your regex has the global flag (g
) but you're only executing it once; that means its lastIndex
is set and the next time you run it, it tries to start from where it left off.
这种行为的原因是您的regex有全局标志(g),但是您只执行一次;这意味着设置了它的lastIndex,下次运行它时,它试图从它停止的地方开始。
Either remove the g
flag, or add
要么删除g标志,要么添加。
re.lastIndex = -1;
...as the first line in the while
loop:
…作为while循环的第一行:
function myFunction() {
var a = ["a", "~@b@~", "~@c@~"]
var re = /~@(.*?)@~/; // <=== Note `g` removed
var i = a.length;
var t;
while (i--) {
var match = re.exec(a[i]);
if (match && match[0] && match[1]) {
a[i] = a[i].replace(match[0], match[1]);
}
}
var res = a.join('/');
document.getElementById("demo").innerHTML = res;
}
<p>
My goal is to print the string: <code>a/b/c</code>. See weird <i>uncomment</i> fix in JS.
<button onclick="myFunction()">Click Here</button>
</p>
<p id="demo"></p>
However, if you leave that g
flag on the regex, you can replace the entire contents of the while
loop with
但是,如果在regex中保留g标志,则可以将while循环的全部内容替换为
a[i] = a[i].replace(re, "$1");
function myFunction() {
var a = ["a", "~@b@~", "~@c@~"]
var re = /~@(.*?)@~/;
var i = a.length;
var t;
// Uncomment below line to see the problem change from ~@b@~ to ~@c@~
//a.reverse();
while (i--) {
a[i] = a[i].replace(re, "$1");
}
var res = a.join('/');
document.getElementById("demo").innerHTML = res;
}
<p>
My goal is to print the string: <code>a/b/c</code>. See weird <i>uncomment</i> fix in JS.
<button onclick="myFunction()">Click Here</button>
</p>
<p id="demo"></p>
...which also has the advantage of handling entries in the form "~@b@~~@c@~"
(because it replaces all occurrences in the string, not just the first one).
…它还具有处理形式为“~@b@~~@c@~”的条目的优势(因为它替换了字符串中的所有事件,而不仅仅是第一个)。
#2
1
Removing the global flag from the regex to change from:
从正则表达式中移除全局标志以更改:
var re = /~@(.*?)@~/g;
to:
:
var re = /~@(.*?)@~/;
should fix this.
应该解决这个问题。