我想编写一个正则表达式来计算一段文本中的空格/制表符/换行符的数量。所以我天真地写了以下内容:-
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);
}
tl;dr:通用模式计数器
// 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()
.
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://stackoverflow.com/a/48195124/16777,但已修复以在零结果情况下实际工作。
('my string'.match(/\s/g) || []).length;
这是@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
?.
是可选的链接运算符。它允许您将调用链接到任意深度,而不必担心一路上是否存在未定义/空值。认为str?.match(re)
是
if (str !== undefined && str !== null) {
return str.match(re);
} else {
return undefined;
}
这与@Paolo Bergantino 的略有不同。他们的写法是这样的:(str || '')
. 这意味着如果str
为假,则返回''
。0 为假。document.all是假的。在我看来,如果有人将它们作为字符串传递给这个函数,那可能是因为程序员错误。因此,我宁愿被告知我在做一些不明智的事情,而不是解决为什么我的长度一直为 0。
??
是无效合并运算符。把它想象成||
更具体的。如果 的左侧||
评估为falsy,则执行右侧。但??
仅在左侧未定义或为空时才执行。
请记住,无效合并运算符 in?.length ?? 0
将返回与 using 相同的内容?.length || 0
。不同之处在于,如果length
返回 0,则不会执行右侧...但无论您使用||
或,结果都将是 0 ??
。
老实说,在这种情况下,我可能会将其更改为,||
因为更多的 JavaScript 开发人员熟悉该运算符。也许有人可以启发我在这种情况下??
vs 的好处||
,如果有的话。
最后,我更改了签名,以便该函数可用于任何正则表达式。
哦,这是一个typescript版本:
const matchCount = (str: string, re: RegExp) => {
return str?.match(re)?.length ?? 0;
};