简体   繁体   English

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

[英]Count number of matches of a regex in Javascript

I wanted to write a regex to count the number of spaces/tabs/newline in a chunk of text.我想编写一个正则表达式来计算一段文本中的空格/制表符/换行符的数量。 So I naively wrote the following:-所以我天真地写了以下内容:-

numSpaces : function(text) { 
    return text.match(/\s/).length; 
}

For some unknown reasons it always returns 1 .由于某些未知原因,它总是返回1 What is the problem with the above statement?上面的说法有什么问题? I have since solved the problem with the following:-从那以后,我用以下方法解决了这个问题:-

numSpaces : function(text) { 
    return (text.split(/\s/).length -1); 
}

tl;dr: Generic Pattern Counter tl;dr:通用模式计数器

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

For those that arrived here looking for a generic way to count the number of occurrences of a regex pattern in a string, and don't want it to fail if there are zero occurrences, this code is what you need.对于那些来到这里寻找一种通用方法来计算字符串中正则表达式模式出现次数的人,并且不希望它在出现次数为零时失败,此代码正是您所需要的。 Here's a demonstration:这是一个演示:

 /* * Example */ const count = (str) => { const re = /[az]{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 '/[az]{3}/g'`) console.log(`'${str2}' has ${count(str2)} occurrences of pattern '/[az]{3}/g'`)

Original Answer原答案

The problem with your initial code is that you are missing the global identifier :您的初始代码的问题在于您缺少全局标识符

>>> 'hi there how are you'.match(/\s/g).length;
4

Without the g part of the regex it will only match the first occurrence and stop there.如果没有正则表达式的g部分,它只会匹配第一次出现并在那里停止。

Also note that your regex will count successive spaces twice:另请注意,您的正则表达式将连续计算两次空格:

>>> 'hi  there'.match(/\s/g).length;
2

If that is not desirable, you could do this:如果这是不可取的,你可以这样做:

>>> 'hi  there'.match(/\s+/g).length;
1

As mentioned in my earlier answer , you can use RegExp.exec() to iterate over all matches and count each occurrence;正如我之前的回答中提到的,您可以使用RegExp.exec()迭代所有匹配项并计算每次出现的次数; the advantage is limited to memory only, because on the whole it's about 20% slower than using String.match() .优势仅限于内存,因为总的来说它比使用String.match()慢约 20%。

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

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

return count;
(('a a a').match(/b/g) || []).length; // 0
(('a a a').match(/a/g) || []).length; // 3

Based on https://stackoverflow.com/a/48195124/16777 but fixed to actually work in zero-results case.基于https://stackoverflow.com/a/48195124/16777,但已修复以在零结果情况下实际工作。

('my string'.match(/\\s/g) || []).length;

This is certainly something that has a lot of traps.这当然是有很多陷阱的东西。 I was working with Paolo Bergantino's answer, and realising that even that has some limitations.我正在使用 Paolo Bergantino 的答案,并意识到即使这样也有一些局限性。 I found working with string representations of dates a good place to quickly find some of the main problems.我发现使用日期的字符串表示是快速找到一些主要问题的好地方。 Start with an input string like this: '12-2-2019 5:1:48.670'从这样的输入字符串开始: '12-2-2019 5:1:48.670'

and set up Paolo's function like this:并像这样设置 Paolo 的函数:

function count(re, str) {
    if (typeof re !== "string") {
        return 0;
    }
    re = (re === '.') ? ('\\' + re) : re;
    var cre = new RegExp(re, 'g');
    return ((str || '').match(cre) || []).length;
}

I wanted the regular expression to be passed in, so that the function is more reusable, secondly, I wanted the parameter to be a string, so that the client doesn't have to make the regex, but simply match on the string, like a standard string utility class method.我希望传入正则表达式,以便函数更可重用,其次,我希望参数是字符串,这样客户端就不必制作正则表达式,而只需匹配字符串,例如标准的字符串实用程序类方法。

Now, here you can see that I'm dealing with issues with the input.现在,在这里您可以看到我正在处理输入问题。 With the following:具有以下内容:

if (typeof re !== "string") {
    return 0;
}

I am ensuring that the input isn't anything like the literal 0 , false , undefined , or null , none of which are strings.我确保输入不是文字0falseundefinednull ,它们都不是字符串。 Since these literals are not in the input string, there should be no matches, but it should match '0' , which is a string.由于这些文字不在输入字符串中,因此应该没有匹配项,但它应该匹配'0' ,这是一个字符串。

With the following:具有以下内容:

re = (re === '.') ? ('\\' + re) : re;

I am dealing with the fact that the RegExp constructor will (I think, wrongly) interpret the string '.'我正在处理这样一个事实,即 RegExp 构造函数将(我认为,错误地)解释字符串'.' as the all character matcher \\.\\作为所有字符匹配器\\.\\

Finally, because I am using the RegExp constructor, I need to give it the global 'g' flag so that it counts all matches, not just the first one, similar to the suggestions in other posts.最后,因为我正在使用 RegExp 构造函数,所以我需要给它全局'g'标志,以便它计算所有匹配项,而不仅仅是第一个,类似于其他帖子中的建议。

I realise that this is an extremely late answer, but it might be helpful to someone stumbling along here.我意识到这是一个非常晚的答案,但它可能对在这里磕磕绊绊的人有所帮助。 BTW here's the TypeScript version:顺便说一句,这里是 TypeScript 版本:

function count(re: string, str: string): number {
    if (typeof re !== 'string') {
        return 0;
    }
    re = (re === '.') ? ('\\' + re) : re;
    const cre = new RegExp(re, 'g');    
    return ((str || '').match(cre) || []).length;
}

Using modern syntax avoids the need to create a dummy array to count length 0使用现代语法避免了创建一个虚拟数组来计算长度 0 的需要

const countMatches = (exp, str) => str.match(exp)?.length ?? 0;

Must pass exp as RegExp and str as String .必须将exp作为RegExp传递,将str作为String传递。

how about like this这样怎么样

function isint(str){
    if(str.match(/\d/g).length==str.length){
        return true;
    }
    else {
         return false
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM