如何在while循环中调整变量范围以匹配CoffeeScript中的所有正则表达式?

时间:2012-12-29 05:16:07

标签: javascript regex node.js coffeescript scope

我在使用coffeescript中的while循环时遇到了一些麻烦。

原始功能如下,the source is this answer

// Return all pattern matches with captured groups
RegExp.prototype.execAll = function(string) {
    var match = null;
    var matches = new Array();
    while (match = this.exec(string)) {
        var matchArray = [];
        for (i in match) {
            if (parseInt(i) == i) {
                matchArray.push(match[i]);
            }
        }
        matches.push(matchArray);
    }
    return matches;
}

按预期工作。我通过js2coffee转换了它,咖啡脚本是:

# Return all pattern matches with captured groups
RegExp::execAll = (string) ->

  matches = new Array()
  match = null
  while match = @exec(string) 
    matchArray = new Array()
    for i of match
      matchArray.push match[i]  if parseInt(i) is i
    matches.push matchArray
  matches

编译为:

RegExp.prototype.execAll = function(string) {
  var i, match, matchArray, matches;
  matches = new Array();
  match = null;
  while (match = this.exec(string)) {
    matchArray = new Array();
    for (i in match) {
      if (parseInt(i) === i) {
        matchArray.push(match[i]);
      }
    }
    matches.push(matchArray);
  }
  return matches;
};

结果是:

[
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  []
]

我认为这不起作用,因为可变范围,因为我能看到的唯一区别是这一行:

RegExp.prototype.execAll = function(string) {
  var i, match, matchArray, matches;

与原作:

RegExp.prototype.execAll = function(string) {
    var match = null;
    var matches = new Array();
    while (match = this.exec(string)) {
        var matchArray = [];

请注意matchArray是如何确定的...我无法找到解决方法,但在我研究过程中,我发现了这些问题Were `do...while` loops left out of CoffeeScript...?How do I declare a variable in a specific scope in coffeescript?而我是几乎没有想法在这里...除了这个循环之外的所有其他方式匹配所有regexp(顺便说一句,我已尝试\gm标志并且它仍然只击中一个匹配)?或者有没有办法在咖啡脚本中使用这个范围?

整个咖啡脚本代码是:

fs = require 'fs'

text = fs.readFileSync('test.md','utf8')

#console.log text

regex = /^(?:@@)(\w+):(.*.)/gm
# Return all pattern matches with captured groups
RegExp::execAll = (string) ->

  matches = new Array()
  match = null
  while match = @exec(string) 
    matchArray = new Array()
    for i of match
      matchArray.push match[i]  if parseInt(i) is i
    matches.push matchArray
  matches

res = regex.execAll text
#console.log regex.exec text
console.log (JSON.stringify(res, null, "  ") )

工作的Javascript 是:

var fs, regex, res, text;

fs = require('fs');

text = fs.readFileSync('test.md', 'utf8');

regex = /^(?:@@)(\w+):(.*.)/gm;

// Return all pattern matches with captured groups
RegExp.prototype.execAll = function(string) {
    var match = null;
    var matches = new Array();
    while (match = this.exec(string)) {
        var matchArray = [];
        for (i in match) {
            if (parseInt(i) == i) {
                matchArray.push(match[i]);
            }
        }
        matches.push(matchArray);
    }
    return matches;
}

res = regex.execAll(text);

//console.log(regex.exec(text));

console.log(JSON.stringify(res, null, "  "));

1 个答案:

答案 0 :(得分:7)

实际问题不是你想象的那样。实际问题是==编译为===。以下是解决问题的方法:

# Return all pattern matches with captured groups
RegExp::execAll = (string) ->
  matches = []
  while match = @exec string
    matches.push(group for group in match)
  matches

但您可能想知道为什么===不起作用。因此,我向您呈现:

为什么===不起作用(在这种情况下)

parseInt(i) == i应该确定i是否是表示整数的字符串。您可以在JavaScript中尝试使用一些值,看看它是否有效。 parseInt(i)是一个数字,而i是一个字符串。在JavaScript中,如果您在字符串和数字上使用==,它将隐式强制执行,测试将按您的预期运行。这种隐式强制通常是意料之外的,所以CoffeeScript不允许它通过没有等效的==运算符,将==(和is)翻译成===,这是第一次比较类型。在这种情况下,数字和字符串将永远不会相等,因此永远不会满足if的条件,因此不会将任何内容推送到数组上。