JS中正規表示式研究(一)

楊軍軍發表於2015-10-14

因為做一道題(http://www.codewars.com/kata/insert-dashes/solutions/javascript),題目如下:

Write a function insertDash(num) that will insert dashes (`-`) between
each two odd numbers in num. For example: if num is 454793 the output
should be 4547-9-3. Don`t count zero as an odd number.

其中一個解答,引起了我對正則的研究興趣,解答如下:

function insertDash(num) {
   return String(num).replace(/([13579])(?=[13579])/g, `$1-`);
}

我對正規表示式中的 正向肯定預查(?=pattern)一直不帶明白,所以趁這個機會研究一下。

下面是我的測試程式碼:

var str = "13579";

var regArr = [
  /([13579])([13579])/g,    // capturing groups
  /([13579])(?:[13579])/g,  // non-capturing groups
  /([13579])(?=[13579])/g   // Assertions 
  ];


regArr.forEach(function(reg){
  console.log("regexp:", reg);
  while((q=reg.exec(str)) != null){
    console.log(q, "lastIndex", reg.lastIndex);
  }
  console.log("result:", str.replace(reg, "$1-"));
});

測試程式碼的輸出:

regexp: /([13579])([13579])/g
["13", "1", "3", index: 0, input: "13579"] "lastIndex" 2
["57", "5", "7", index: 2, input: "13579"] "lastIndex" 4
result: 1-5-9
regexp: /([13579])(?:[13579])/g
["13", "1", index: 0, input: "13579"] "lastIndex" 2
["57", "5", index: 2, input: "13579"] "lastIndex" 4
result: 1-5-9
regexp: /([13579])(?=[13579])/g
["1", "1", index: 0, input: "13579"] "lastIndex" 1
["3", "3", index: 1, input: "13579"] "lastIndex" 2
["5", "5", index: 2, input: "13579"] "lastIndex" 3
["7", "7", index: 3, input: "13579"] "lastIndex" 4
result: 1-3-5-7-9

regexObj.exec(str) 返回結果是一個陣列,其中第一個成員是所匹配的字串,接下來是捕獲的分組,它有一個index 屬性,表明是從哪個地方開始匹配的。與此同時,reg 物件的 lastIndex 更新為下一次開始匹配的索引值。

  • /([13579])([13579])/g 每次匹配兩個字元,下次開始匹配位置 +2, 每次產生兩個捕獲分組;

  • /([13579])(?:[13579])/g, 每次也匹配兩個字元,下次開始匹配位置 +2, 由於使用了非捕獲匹配,所以每次產生一個捕獲分組;

  • /([13579])(?=[13579])/g, (?=[13579])只幫助定位匹配的位置,並不屬於匹配的字元,所以每次匹配一個字元,所以下一次開始匹配位置 +1 ;

參考

  1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp

  2. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec

相關文章