Javascript에서 정규식 일치 수 계산


98

텍스트 청크에서 공백 / 탭 / 줄 바꿈의 수를 계산하는 정규식을 작성하고 싶었습니다. 그래서 순진하게 다음과 같이 썼습니다.

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

알 수없는 이유로 항상을 반환합니다 1. 위 진술의 문제점은 무엇입니까? 나는 이후 다음과 같은 문제를 해결했습니다.

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

답변:


192

tl; dr : 일반 패턴 카운터

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

여기에 도착한 사람들은 문자열에서 정규식 패턴의 발생 횟수를 계산하는 일반적인 방법을 찾고 있고 0 발생이 발생하더라도 실패하지 않기를 원하는 경우이 코드가 필요합니다. 다음은 데모입니다.

/*
 *  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

5
입력에 공백이 하나 이상 있으면 작동합니다. 그렇지 않으면 match ()가 짜증나게 null을 반환합니다.
sfink 2011

3
sfink가 맞습니다. match ()가 null을 반환했는지 확실히 확인하고 싶습니다.var result = text.match(/\s/g); return result ? result.length : 0;
Gras Double

37
다음 구조를 사용하여 null로부터 보호 할 수도 있습니다.( str.match(...) || [] ).length
a'r

11

이전 답변 에서 언급했듯이 RegExp.exec()모든 일치 항목을 반복하고 각 항목을 계산 하는 데 사용할 수 있습니다 . 전체적으로 사용하는 것보다 약 20 % 더 느리기 때문에 장점은 메모리에만 국한됩니다 String.match().

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

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

return count;


2

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


1
난 당신이를 넣어 생각하는 || []잘못된 장소에, 그것은해야('my string'.match(/\s/g) || []).length
woojoo666

0

이것은 확실히 많은 함정이있는 것입니다. 나는 Paolo Bergantino의 대답으로 작업하고 있었고 그것에도 약간의 한계가 있음을 깨달았습니다. 날짜의 문자열 표현으로 작업하는 것이 몇 가지 주요 문제를 빠르게 찾을 수있는 좋은 장소임을 알았습니다. 다음과 같은 입력 문자열로 시작합니다. '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;

RegExp 생성자가 문자열 '.'을 모든 문자 일치 자로 해석한다는 사실을 다루고 있습니다.\.\

마지막으로 RegExp 생성자를 사용하고 있기 때문에 'g'다른 게시물의 제안과 유사하게 첫 번째 항목뿐만 아니라 모든 일치 항목을 계산하도록 전역 플래그 를 제공해야합니다 .

나는 이것이 매우 늦은 대답이라는 것을 알고 있지만 여기에서 걸림돌이되는 누군가에게 도움이 될 수 있습니다. BTW는 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;
}

-2

이건 어때

function isint(str){
    if(str.match(/\d/g).length==str.length){
        return true;
    }
    else {
         return false
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.