【问题标题】:Find all function signatures with more than 2 arguments in javascript在javascript中查找所有具有超过2个参数的函数签名
【发布时间】:2015-07-23 21:24:42
【问题描述】:

我需要找到所有接受超过 X 个参数的函数签名(比如 2)。 我尝试了类似function\s*\((\w*,){3,10} 之类的方法(它可以捕获所有带有 3-10 个参数的签名,但它不起作用。它的变化会产生意想不到的结果。我想我只是不太擅长正则表达式,但感谢任何帮助.

更新:我应该指出我正在编写一种代码检查工具。在许多事情中,我想找出接受超过 2 个参数的函数(因为我提倡使用带有少量参数的函数,以及在构造函数的情况下使用 1 个参数)。所以我不能打电话给arguments.length等等。

【问题讨论】:

  • 函数有一个length 属性...
  • 好吧,JavaScript 因为大多数编程语言都不是常规语言。因此,正则表达式无法完全掌握语言。你需要一个上下文无关语法来做到这一点...
  • 你不需要 CFG 来获得一个相当好的参数解析器......我认为你只是在 (\w*) 组之后缺少一些可选的空格,你需要使逗号也是可选的(所以,(\w*,?)),以便它匹配单参数大小写。如果您正在寻找非匿名函数,您还需要在其中添加一个 \w+ 作为名称。
  • @elclanrs 即使​​他想找到方法,也不代表它们属于当前脚本。他可以尝试在他的 php-files (java-doc-style) 中找到某些方法
  • 您需要将 \w 逗号和空格放在一个字符组中,并将其放在括号内,并有一个终止转义的括号

标签: javascript regex


【解决方案1】:

想想“简单”:

  • 一个方法通常有(...)\(\)
  • 具有 3 个参数的方法在括号内有 2 个,\(,{2,2}\)
  • 每个, 需要在前面和后面跟字符串:\((?:\w+,\w+){2,2}\)
  • 没有发生双重匹配,所以不起作用 - 让我们将前导字符串设为强制性,以下是可选的,但最后它需要以一个字符串停止: \((?:\w+,\w*){2,2}\w+\)
  • 通常方法声明以function name开头:function\s+\w+\s*\((?:\w*,\w*){2,2}\)
  • 最后,参数周围可能有空格:function\s+\w+\s*\((?:\s*\w+\s*,\s*\w*\s*){2,2}\w+\s*\)

给你。这应该涵盖所有“通用”方法声明,除了无名 lambda 表达式:

function\s+\w+\s*\((?:\s*\w+\s*,\s*\w*\s*){2,2}\w+\s*\)

Debuggex Demo

匹配 两到两个 逗号将找到具有 3 个参数的签名。 Matchint 2 到 5 个逗号将找到具有 3 到 6 个参数的签名。

【讨论】:

  • 一条评论:这将允许function test (foo, qux quux, test test2)(因此参数可以分成两个词)。此外,它不匹配具有 4 个参数的函数。鉴于 js 代码是正确的,这并不是真正的问题。但这确实是一个很好的解决方案。
  • 这是一个非常明确的答案,我对此表示赞同,但恰巧 CommuSoft 的答案产生了更多的积极影响。鉴于事实,我接受他的回答是正确的,但非常感谢您的指点!
  • @JoeMinichino:我认为通过将{2,2} 替换为{2,} 并将\w+\s* 替换为.*,它将正常工作...
  • @CommuSoft 对于正好 4 个参数,它将是 {3,3} - 对于 两到四个 {1,3}。您对“误报”是正确的,但我认为 javascript 是正确的。
  • @CommuSoft 没有冒犯 :-) 只是想概述它是一个 example 给出的,而不是整体解决方案。
【解决方案2】:

首先,JavaScript 不是一种正则语言,因此无法使用正则表达式来完全掌握该语言,因此有可能你要么接受误报,要么接受误报。

一个可能接近的正则表达式是:

function(?:\s+\w+)*\s*\(([^),]*)(\s*,\s*[^),]*){2,}\)

正则表达式的工作方式如下:

  • function 搜索 function 关键字。
  • 接下来有一个可选组\s+\w+,该组用于与函数名进行标识:可以定义一个不带名称的anonymous function,因此该组必须是可选的。
  • 接下来\s*\(有任意数量的空格和括号打开参数列表;
  • 现在,在括号之间,我们开始寻找参数。为了涵盖(大多数)情况,我们将参数定义为[^,)]*(不包含逗号和右括号的字符序列)。
  • 现在对于下一个参数,我们需要跳过一个逗号,这是由\s*,\s* 模式强制执行的(\s* 实际上是不必要的)。接下来又是一组参数名称,当然我们需要跳过至少两个逗号。
  • 最后是一个(可选的)右括号。

【讨论】:

  • 如何得到假阴性?我可以在字符串/cmets 中看到函数的误报,但函数本身必须遵循特定的语法,可以由正则表达式定义,对吧?
  • 好吧……他不想写一个基于正则表达式的javascript解析器——只要找到方法签名……
  • 再次语言 本身 不是 正规的,但这并不意味着 它的一个子部分(带有约束)不能定期解析。
  • @ap:目前所谓的正则表达式并不是理论上意义上的正则表达式。
  • @CasimiretHippolyte:见here常规语言在前瞻下关闭。尽管它是一个很好的语法糖,但它并没有添加任何正则表达式的功能。字符组、可选组等也是如此……确实,例如,正则表达式的严格定义允许使用 Kleene 星号,但大多数非 Perl 扩展不会增加基本功能。
【解决方案3】:

您希望使用function\s*\w+\s*\(\s*(\w+,?){3,10} 来匹配非匿名(命名)函数,并删除\w+\s* 以获取function\s*\(\s*(\w+,?){3,10} 以获取匿名函数。

这些可以组合得到function\s*(?:\w+\s*)?\(\s*(\w+,?){3,10}?:是非捕获组)

【讨论】:

  • 这也将匹配function(fobar),因为逗号是可选的。
  • @CommuSoft 你错了,不是因为最小组{3,10} - 它是不正确的其他原因,但你似乎错过了他们。
  • regex101.com/r/hG0mS0/1。您重复 (\w+,?) 三次或更多次,因此对于每个组,我只选择一个字符(foo),因为逗号是可选的每次 .它永远不会被选中。
  • 还有其他一些原因:您确实忘记在逗号前后允许空格...
  • 你很生气早点错了,嗯?很酷,放手吧,伙计。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-26
  • 1970-01-01
  • 2021-01-27
  • 1970-01-01
  • 2019-10-11
  • 2020-10-01
相关资源
最近更新 更多