【问题标题】:Regular expression to match JavaScript function匹配 JavaScript 函数的正则表达式
【发布时间】:2011-05-11 09:18:21
【问题描述】:

是否有匹配 JavaScript 函数的正则表达式?

喜欢

function abc(var1, var2){
  ..
}

// and

abc : function(var1, var2){
  ...
},

【问题讨论】:

  • 你认为你做到了。但你没有。你到底想完成什么?

标签: javascript regex


【解决方案1】:

我知道这个问题已有 5 年的历史,但与其他人所说的相反,我实际上已经编造了一个非常有效的模式来按照您的要求进行操作。尽管相当复杂,但我在自己的项目中多次使用它,但我还没有遇到过问题……希望我早点看到这个问题。希望这会有所帮助(如果不适合您,希望对那些正在寻找类似解决方案的人有所帮助)

function\s*([A-z0-9]+)?\s*\((?:[^)(]+|\((?:[^)(]+|\([^)(]*\))*\))*\)\s*\{(?:[^}{]+|\{(?:[^}{]+|\{[^}{]*\})*\})*\}

【讨论】:

  • 可爱,但这里是一个没有正确解析的简单示例:function() { return "}" }
  • @ZsoltSzatmari 普通人 - 虽然它是有效的,但不知道为什么你会想要它作为一个函数......
  • 这是另一个不起作用的简单示例:function() {if(A){}else{if(B){if(C){}}}}
【解决方案2】:

在 JS 中,函数可以包含函数(而函数又可以包含函数,依此类推):

x = function() {
  this.y = function() { /* ... */ };
  function z() { /* ... */ }
};

此外,您可以使用字符串文字或 cmets,它们可以包含(子)字符串,它们看起来像函数:

var s = "function notAFunction(){}";
/* 
function alsoNotAFunction(){}
*/

或包含您的正则表达式可能会遇到的部分函数:

function f() {
  var s = "not a closing bracket: } ";
}

所以,回答你的问题是什么正则表达式可以匹配 JS 中的函数:它不存在。您应该/可以为此使用适当的解析器。

【讨论】:

    【解决方案3】:

    你想用正则表达式解析 JS 吗?如果是这样,不要。 Regex 是一个非常糟糕的解析器,请参阅这些问题。

    When should I use a parser?

    RegEx match open tags except XHTML self-contained tags

    If you're not supposed to use Regular Expressions to parse HTML, then how are HTML parsers written?

    【讨论】:

      【解决方案4】:

      今天我面临同样的挑战,我想在一个字符串中找到function definationsfunction usages

      并使用名为esprima 的解析器解决了这个问题。

      (注意:这是针对 nodejs 的,不是浏览器 javascript。使用 npm i esprima clipboardy 运行依赖项并将代码放入 index.js 并使用 node index.js 运行它)

      var esprima = require('esprima');
      const clipboardy = require('clipboardy');
      var program = `
      const answer = 42;
      function foo(){
          alert("hi")
      }
      `;
      
      //esprima.tokenize(program)
      var entries = []
      parsed = esprima.parseScript(program, {}, function (node, meta) {
                  entries.push({
                      start: meta.start.offset,
                      end: meta.end.offset,
                      node: node
                  });
          })
      
      clipboardy.writeSync(JSON.stringify(entries, null, 2));
      console.log('full parsed data copied to clipboard!')
      
      //find function calls
      var functionCalls = entries.filter(e => e.node.type == "CallExpression")
      console.log('function calls: ' + JSON.stringify(functionCalls.map (a => {return {name: a.node.callee.name, start: a.start, end: a.end}})))
      
      //find alert function calls
      var alertFunctionCalls = entries.filter(e => e.node.type == 'CallExpression' && (e.node.callee.name == 'alert'))
      console.log('alert function calls: ' + JSON.stringify(alertFunctionCalls.map (a => {return {start: a.start, end: a.end}})))
      
      //find function definations
      var functionDeclarations = entries.filter(e => e.node.type == 'FunctionDeclaration')
      console.log('function definations: ' + JSON.stringify(functionDeclarations.map (a => {return {name: a.node.id.name, start: a.start, end: a.end}})))
      
      //find foo() function defination
      var fooFunctionDeclaration = entries.filter(e => e.node.type == 'FunctionDeclaration' && e.node.id.name == 'foo')
      console.log('foo function definations: ' + JSON.stringify(functionDeclarations.map (a => {return {start: a.start, end: a.end}})))
      
      //remove alert function calls
      var program2 = program
      alertFunctionCalls.sort((a, b) => { return b.end - a.end }).forEach(n => {
          program2 = program2.substring(0, n.start) + program2.substring(n.end);
      });
      console.log('program after removing alert function calls: ' + program2)
      
      

      【讨论】:

        【解决方案5】:

        前段时间我写了一个正则表达式来检测函数,所以我们可以检查是否有为每个函数编写的文档,不是那么容易理解,不是一个惊人的正则表达式,但它似乎涵盖了很多不同的函数声明的类型:

        ^(?:[\s]+)?(?:const|let|var|)?(?:[a-z0-9.]+(?:\.prototype)?)?(?:\s)?(?:[a-z0-9-_]+\s?=)?\s?(?:[a-z0-9]+\s+\:\s+)?(?:function\s?)?(?:[a-z0-9_-]+)?\s?\(.*\)\s?(?:.+)?([=>]:)?\{(?:(?:[^}{]+|\{(?:[^}{]+|\{[^}{]*\})*\})*\}(?:\s?\(.*\)\s?\)\s?)?)?(?:\;)?

        查看我在这里测试过的类型:https://regex101.com/r/WGqfm8/9/

        这不会处理所有情况,但应该抓住大部分!

        我故意没有添加的东西:

        // won't find
        const filterFn = apples.filter(() => {});
        // won't find
        const filterFn = apples.filter(function(){});
        

        肯定有一些我没有涵盖的内容,但我尝试涵盖大部分基础知识,您只需要从匹配组中修剪空白

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-07-14
          • 2017-08-16
          • 2011-11-29
          • 2012-09-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多