Підрахуйте кількість збігів регулярного виразу в Javascript


98

Я хотів написати регулярний вираз, щоб підрахувати кількість пробілів / вкладок / нового рядка в шматку тексту. Тому я наївно написав наступне:

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

З незрозумілих причин він завжди повертається 1. У чому проблема вищезазначеного твердження? З тих пір я вирішив проблему наступним чином: -

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

Відповіді:


191

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

5
Це працює, якщо у вашому введенні є хоча б один пробіл. В іншому випадку match () надокучливо повертає null.
sfink

3
sfink має рацію, ви точно хочете перевірити, чи match () повернув null:var result = text.match(/\s/g); return result ? result.length : 0;
Gras Double

37
Ви також можете захистити від нуля, використовуючи цю конструкцію:( 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;



0

Це, звичайно, щось, що має багато пасток. Я працював із відповіддю Паоло Бергантіно і розумів, що навіть це має певні обмеження. Я знайшов роботу з рядковими поданнями дат хорошим місцем для швидкого пошуку деяких основних проблем. Почніть із вхідного рядка наступним чином: '12-2-2019 5:1:48.670'

і налаштуйте функцію Паоло так:

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'прапор, щоб він враховував усі збіги, а не лише перший, подібно до пропозицій в інших публікаціях.

Я усвідомлюю, що це надзвичайно пізня відповідь, але це може бути корисно комусь, хто тут спотикається. До речі, ось версія 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
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.