计算Javascript中正则表达式的匹配数

wai*_*wai 86 javascript regex

我想编写一个正则表达式来计算一大块文本中的空格/制表符/换行符的数量.所以我天真地写了以下内容: -

numSpaces : function(text) { 
    return text.match(/\s/).length; 
}
Run Code Online (Sandbox Code Playgroud)

由于一些不明原因它总是返回1.上述陈述有什么问题?我已经解决了以下问题: -

numSpaces : function(text) { 
    return (text.split(/\s/).length -1); 
}
Run Code Online (Sandbox Code Playgroud)

Pao*_*ino 174

tl; dr:通用模式计数器

// THIS IS WHAT YOU NEED
const count = (str) => {
  const re = /YOUR_PATTERN_HERE/g
  return ((str || '').match(re) || []).length
}
Run Code Online (Sandbox Code Playgroud)

对于那些到达这里的人来说,寻找一种通用的方法来计算字符串中正则表达式模式的出现次数,并且如果没有出现则不希望它失败,这个代码就是你需要的.这是一个演示:

/*
 *  Example
 */

const count = (str) => {
  const re = /[a-z]{3}/g
  return ((str || '').match(re) || []).length
}

const str1 = 'abc, def, ghi'
const str2 = 'ABC, DEF, GHI'

console.log(`'${str1}' has ${count(str1)} occurrences of pattern '/[a-z]{3}/g'`)
console.log(`'${str2}' has ${count(str2)} occurrences of pattern '/[a-z]{3}/g'`)
Run Code Online (Sandbox Code Playgroud)

原始答案

您的初始代码的问题是您缺少全局标识符:

>>> 'hi there how are you'.match(/\s/g).length;
4
Run Code Online (Sandbox Code Playgroud)

如果没有g正则表达式的部分,它将只匹配第一次出现并停在那里.

另请注意,您的正则表达式将连续计算两次空格:

>>> 'hi  there'.match(/\s/g).length;
2
Run Code Online (Sandbox Code Playgroud)

如果这不可取,您可以这样做:

>>> 'hi  there'.match(/\s+/g).length;
1
Run Code Online (Sandbox Code Playgroud)

  • 您还可以使用以下结构来防止null:`(str.match(...)|| []).length` (37认同)
  • 只要输入中至少有一个空格,这就可以工作.否则,match()烦人地返回null. (5认同)
  • sfink是对的,你肯定想检查match()是否返回null:`var result = text.match(/\s/g); 返回结果?result.length:0;` (3认同)

Ja͢*_*͢ck 10

正如我之前的回答中所提到的,您可以使用RegExp.exec()迭代所有匹配并计算每次出现的次数; 优势仅限于内存,因为总体上它比使用速度慢约20%String.match().

var re = /\s/g,
count = 0;

while (re.exec(text) !== null) {
    ++count;
}

return count;
Run Code Online (Sandbox Code Playgroud)


Kev*_*Kev 9

(('a a a').match(/b/g) || []).length; // 0
(('a a a').match(/a/g) || []).length; // 3
Run Code Online (Sandbox Code Playgroud)

基于/sf/answers/3373658711/,但已修复在零结果情况下实际工作。


Dan*_*lan 5

这是与 @Paolo Bergantino 的答案类似的解决方案,但使用现代操作员。下面我会解释一下。

    const matchCount = (str, re) => {
      return str?.match(re)?.length ?? 0;
    };

    // usage
    
    let numSpaces = matchCount(undefined, /\s/g);
    console.log(numSpaces); // 0
    numSpaces = matchCount("foobarbaz", /\s/g);
    console.log(numSpaces); // 0
    numSpaces = matchCount("foo bar baz", /\s/g);
    console.log(numSpaces); // 2
Run Code Online (Sandbox Code Playgroud)

?.可选的链接运算符。它允许您根据需要将调用链接到任意深度,而不必担心沿途是否存在未定义/空值。认为str?.match(re)

if (str !== undefined && str !== null) {
    return str.match(re);
} else {
    return undefined;
}
Run Code Online (Sandbox Code Playgroud)

这与@Paolo Bergantino 的略有不同。他们的写法是这样的:(str || '')。这意味着如果str,则返回''。0 是假的。document.all是假的。在我看来,如果有人将它们作为字符串传递给这个函数,那可能是因为程序员的错误。因此,我宁愿被告知我正在做一些不明智的事情,而不是解决为什么我的长度总是为 0。

??空合并运算符。将其视为||更具体的。如果 的左侧||计算结果为falsy,则执行右侧。但??仅当左侧未定义或为空时才执行。

请记住, in 中的空合并运算符?.length ?? 0将返回与使用 相同的结果?.length || 0。区别在于,如果length返回 0,则不会执行右侧...但无论您使用||或,结果都将是 0 ??

老实说,在这种情况下我可能会将其更改为,||因为更多的 JavaScript 开发人员熟悉该运算符。也许有人可以启发我在这种情况下??vs的好处||(如果存在的话)。

最后,我更改了签名,以便该函数可以用于任何正则表达式。

哦,这是一个打字稿版本:

    const matchCount = (str: string, re: RegExp) => {
      return str?.match(re)?.length ?? 0;
    };
Run Code Online (Sandbox Code Playgroud)