改进了我对正则表达式匹配的可怕切换语句

时间:2015-01-13 08:11:01

标签: javascript regex node.js switch-statement

我正试图摆脱在node.js中使用可怕的切换案例。我正在寻找一种更有效的方法来测试针对各种正则表达式案例的输入。根据匹配的情况,我要么触发事件,要么在运行另一个函数之前对输入进行一些转换。

为了保存一段很长的代码,我将我的功能减少到了下面的骨架,因此它显示了对开关的关注。

我已经看过使用.map返回真假的可能性,但我不确定如何最好地实现它。

关于最佳方法的任何建议或建议?

function ParseLogMessages(message, config, callback){
var _this = this;

try {
//Define regex in order to match strings based on case
_this.to_group = new RegExp("^\\[\\d{2}:\\d{2}\\]\\s+\\w+\\s+tg+\\s\\>{3}");
_this.from_group=new RegExp("^\\[\\d\\d:\\d\\d\\]\\s\\w+\\s\\w+\\s\\>{3}");
_this.to_person = new RegExp("^\\[\\d{2}:\\d{2}\\]\\s[a-zA-Z0-9 \\- _]+\\s\\<{3}.+");
_this.from_person = new RegExp("^\\[\\d{2}:\\d{2}\\]\\s\\w+\\s\\>{3}");
_this.contact = new RegExp("(User #+\\d+:)");


_this.contact = new RegExp("(User #+\\d+:)");

//Test message against each to find type
switch (true){
    //Message sent to a group chat
    case _this.to_group.test(_this.payload.raw):
    break;

    //Message from a group chat
    case _this.from_group.test(_this.payload.raw):
    break;

    //Message sent to a person from the bot
    case _this.to_person.test(_this.payload.raw):
    break;

    //Message sent from a person to the bot
    case _this.from_person.test(_this.payload.raw):         
    break;

    //Contact shared
    case _this.contact.test(_this.payload.raw):     
    break;

    default:
    break;


}

callback(null,"Logfile message parsed ok!");

  } catch(err) {
    log.error(err);
    return callback(err,null);
  }

}

3 个答案:

答案 0 :(得分:5)

您可以创建一个正则表达式/函数对数组并循环遍历数组:

_this.tests = [
    { regex: new RegExp("^\\[\\d{2}:\\d{2}\\]\\s+\\w+\\s+tg+\\s\\>{3}"), // to_group
      action: ... // action for to_group
    },
    { regex : new RegExp("^\\[\\d\\d:\\d\\d\\]\\s\\w+\\s\\w+\\s\\>{3}"), // from_group
      action: ... // action for from_group
    },
    // etc.
];

然后,您可以在测试工作时循环遍历数组,测试和中断:

for (i=0; i<tests.length; ++i) {
    if (tests[i].regex.test(_this.payload.raw) {
        tests[i].action();
        break;
    }
}

答案 1 :(得分:2)

您可以将对象放在数组中并调用test函数,直到返回true:

var o = [
  _this.to_group,
  _this.from_group,
  _this.to_person,
  _this.from_person,
  _this.contact
];
for (var i in o) {
  if (o[i].test(_this.payload.raw)) {
    // got a match
    break;
  }
}

答案 2 :(得分:0)

您想要的是将其转换为关联数组并与循环匹配。未经测试的代码应该有效:

let patterns = {
    "^\\[\\d{2}:\\d{2}\\]\\s+\\w+\\s+tg+\\s\\>{3}": funcToGroup /* code for this case, preferably a [reference to a] function object without the parens */,
    "^\\[\\d\\d:\\d\\d\\]\\s\\w+\\s\\w+\\s\\>{3}": function () {
        // An inline anonymous function is also fine
    },
    "^\\[\\d{2}:\\d{2}\\]\\s[a-zA-Z0-9 \\- _]+\\s\\<{3}.+": funcToPerson,
    "^\\[\\d{2}:\\d{2}\\]\\s\\w+\\s\\>{3}": funcFromPerson,
    "(User #+\\d+:)": funcContactShared
};

for (let pat in _this.patterns) {
    if (new RegExp(pat).test(_this.payload.raw)) {
        _this.patterns[pat]();  // Actually execute the relevant case
    }
}

这应该处理try块中的所有代码。