我想编写一个正则表达式来计算一段文本中空格/制表符/换行符的数量。所以我天真地编写了以下代码:
numSpaces : function(text) {
return text.match(/\s/).length;
}
因为某些未知的原因,它总是返回1
。上述语句有什么问题?我随后通过以下方式解决了这个问题:
numSpaces : function(text) {
return (text.split(/\s/).length -1);
}
我想编写一个正则表达式来计算一段文本中空格/制表符/换行符的数量。所以我天真地编写了以下代码:
numSpaces : function(text) {
return text.match(/\s/).length;
}
因为某些未知的原因,它总是返回1
。上述语句有什么问题?我随后通过以下方式解决了这个问题:
numSpaces : function(text) {
return (text.split(/\s/).length -1);
}
简述:通用模式计数器
// THIS IS WHAT YOU NEED
const count = (str) => {
const re = /YOUR_PATTERN_HERE/g
return ((str || '').match(re) || []).length
}
如果您在这里寻找一种通用的方法来计算字符串中正则表达式模式出现次数,而且不希望在没有出现任何匹配时出现错误,那么这段代码就是您需要的。下面是一个演示:
/*
* 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'`)
原始回答
您初始代码的问题在于缺少了全局标识符:
>>> 'hi there how are you'.match(/\s/g).length;
4
如果正则表达式中没有包含g
,它只会匹配第一次出现并停止。
此外,请注意您的正则表达式将两次计算连续空格:
>>> 'hi there'.match(/\s/g).length;
2
如果不想那样做,你可以这样:
>>> 'hi there'.match(/\s+/g).length;
1
正如我在早先回答中提到的那样,您可以使用RegExp.exec()
来迭代所有匹配项并计算每个出现次数。它的优点仅限于内存使用,因为整体而言,它比使用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
基于https://dev59.com/3nNA5IYBdhLWcg3wI6V4#48195124,但修复了在零结果情况下实际工作的问题。
这是与@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
?.
是可选链操作符。它允许您在调用链中深入任意层级,而无需担心路径上是否存在undefined/null。把str?.match(re)
想象成
if (str !== undefined && str !== null) {
return str.match(re);
} else {
return undefined;
}
(str || '')
。这意味着如果str
为假值,则返回''
。0是假值。document.all也是假值。在我看来,如果有人将它们作为字符串传递给此函数,那可能是由于程序员的错误。因此,我更愿意知道我正在做一些非常规操作,而不是调试为什么我一直得到长度为0。
??
是nullish coalescing operator。将其视为更具体的||
。如果||
的左侧求值结果为假值,则执行右侧操作。但是,??
仅在左侧操作数未定义或为空时执行。?.length ?? 0
中使用的nullish coalescing operator将返回与使用?.length || 0
相同的结果。区别在于,如果length
返回0,则它不会执行右侧操作...但无论使用||
还是??
,结果都将是0。||
,因为更多的JavaScript开发人员熟悉那个运算符。如果有任何存在的话,也许有人能启发我在此情况下使用??
与||
的好处。 const matchCount = (str: string, re: RegExp) => {
return str?.match(re)?.length ?? 0;
};
('my string'.match(/\s/g) || []).length;
|| []
放错了位置,应该是 ('my string'.match(/\s/g) || []).length
。 - woojoo666'12-2-2019 5:1:48.670'
并像这样设置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;
}
if (typeof re !== "string") {
return 0;
}
0
、false
、undefined
或null
,这些都不是字符串。由于这些字面量不在输入字符串中,所以不应该匹配任何内容,但应该匹配'0'
,因为它是一个字符串。re = (re === '.') ? ('\\' + re) : re;
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;
}
这个问题似乎已经解决了,但我还没看到这个版本,它可能更易读,并且符合一些代码库的风格。
const numberOfResults = [...str.matchAll(/YOUR_REGEX/g)].length;
使用现代语法可以避免创建虚拟数组来计算长度为0的需要。
const countMatches = (exp, str) => str.match(exp)?.length ?? 0;
exp
作为RegExp
传递,并将str
作为String
传递。这样怎么样?
function isint(str){
if(str.match(/\d/g).length==str.length){
return true;
}
else {
return false
}
}
var result = text.match(/\s/g); return result ? result.length : 0;
。 - Gras Double(str.match(...) || []).length
。 - a'r('string'.match(/\s/g) || []).length
有什么问题? - João Pimentel Ferreirastr
为空,则str.match()
会失败,但(str || '').match()
不会。 - jkdev