Подсчет кошек с регулярными выражениями - PullRequest
2 голосов
/ 19 марта 2011

Итак, я хочу сопоставить строку со словом «кошка» несколько раз, например:

"cat cat cat cat cat"

или

"cat   cat cat  cat"

Если есть что-то еще, кроме "кошки" или пробела, я не хочу совпадать. Так что я могу сделать:

^(cat\s*)+$

Однако я хочу выяснить, сколько кошек появляется в строке. Один из способов сделать это - подсчитать количество групп, однако приведенное выше регулярное выражение даст мне только одну группу с первым котом, а не захват для каждой кошки. Есть ли способ сделать это с помощью регулярных выражений?

Ответы [ 7 ]

5 голосов
/ 19 марта 2011

Я не вижу никого, кто бы упоминал то, что я считаю очевидным ответом, используя строку сканирования:

str = "cat cat cat    catcat"
str.scan('cat').size #=> 5

Если у вас просто есть для использования регулярного выражения:

str.scan(/cat/).size #=> 5

Если вы хотите поймать только уникальные, а не случайные совпадения:

str.scan(/\bcat\b/).size #=> 3

РЕДАКТИРОВАТЬ:

@ sawa указывает, что есть (значительное)возможность неверного толкования вопроса ОП.Это охватывает случаи, когда OP не хотел, чтобы выполнялся поиск, если в строке было что-то кроме cat и " ".

str.scan('cat').size if str.gsub(/(?:cat| )+/, '').empty? #=> 5

Другие варианты в моем предыдущем разделе все еще могут быть применены.

И, поскольку "пробел" может означать больше, чем простой пробел, "\s" также должен нормально работать.

3 голосов
/ 19 марта 2011

Обратите внимание, что исходное регулярное выражение Майка, а также Томалак, Мартен и ответ тэгмана дают неправильный счет, если в строке присутствуют последовательные экземпляры 'cat' (если вы не хотите рассматривать 'catcat' как два экземпляра слова ' кошка'). Следующее не решает эту проблему.

def count_if_match
  delimiters = strip.split('cat')
  delimiters.length+1 if delimiters.all?{|s| s =~ / +/}
end

' cat   cat cat  cat'.count_if_match # => 4
' catcat cat cat'.count_if_match # => nil
2 голосов
/ 19 марта 2011

Вы хотите сделать две разные вещи - проверить строку и подсчитать число вхождений.Обычно вы не можете сделать эти две вещи за один шаг.

var str   = "cat cat cat cat cat";
var count = 0;

if ( /^(cat\s*)+$/.test(str) ) {
  count = str.match(/cat/g).length;
}

В регулярном выражении .NET у вас есть Group.Captures , в котором перечислены все вхождения, в которых была найдена группа, а не только последняя., как и в других двигателях регулярных выражений.Здесь вы можете выполнить как проверку, так и подсчет за один шаг.

0 голосов
/ 24 сентября 2013
"cat   cat cat  cat".split.count{|w|
    break false unless w == 'cat'

    true
}
0 голосов
/ 19 марта 2011

Рубиновый путь без регулярных выражений будет:

string = "cat   cat cat  cat"
def match_cat(string)
  cat_array = string.split
  count = cat_array.size
  cat_array.uniq == ["cat"] ? count : false
end
match_cat(string)
=> 4
0 голосов
/ 19 марта 2011

Это последний кот, которого вы захватили. Это происходит из-за жадности и способа работы групп захвата . Я не думаю, что возможно получить более одного захвата из группы. Лучшее, что вы можете сделать, это, вероятно:

str = "cat   cat cat  cat"

matchdata = str.match(/^((?:cat\s*)+)$/)
=> #<MatchData "cat   cat cat  cat" 1:"cat   cat cat  cat"> 

matchdata[0].split(/\s+/).size
=> 4
0 голосов
/ 19 марта 2011

Рассмотрите возможность перевода пробелов в символы новой строки, затем посчитайте строки, соответствующие регулярному выражению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...