正则表达式匹配

时间:2016-11-27 17:03:39

标签: javascript regex

Here is a Codepen version

我的目标是迭代数组的元素,搜索匹配~@某事@~的正则表达式,删除识别匹配的“书挡”,然后.join()数组。在以下示例中,结果应类似于a/b/c

然而,我得到了结果a/~@b@~/c。为了让事情更加混乱,当我颠倒数组元素的顺序时,问题结果会从~@b@~变为~@c@~。而且,最后,为了使事情变得非常奇怪,问题似乎通过添加一个简单的test方法来解决,该方法本身总是返回值false。请参阅代码中的注释。并亲自看看。

造成这种奇怪行为的原因是什么?什么是迭代这些元素并进行我描述的替换的正确方法?

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 个答案:

答案 0 :(得分:2)

行为的原因是你的正则表达式有全局标志(g),但你只执行一次;这意味着它已设置lastIndex,下次运行它时,它会尝试从它停止的位置开始。

删除g标记,或添加

re.lastIndex = -1;

...作为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>

然而,如果您在正则表达式上留下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>

...它还具有处理"~@b@~~@c@~"形式的条目的优势(因为它替换了字符串中的所有匹配项,而不仅仅是第一个)。

答案 1 :(得分:1)

从正则表达式中删除全局标志以从:

更改
var re = /~@(.*?)@~/g;

为:

var re = /~@(.*?)@~/;

应该解决这个问题。