2015-02-28 5 views
13

После нескольких часов поиска я решил задать этот вопрос. Почему это регулярное выражение: ^(dog).+?(cat)? не работает, поскольку я думаю, что он должен работать (захватить первую собаку и кошку, если она есть)? Что мне здесь не хватает?Дополнительная группа захвата Regex?

dog, cat 
dog, dog, cat 
dog, dog, dog 

ответ

17

Причина, по которой вы не получаете дополнительный cat после того, как неохотно квалифицированные .+?, что она является необязательной и не закреплено: двигатель не было вынужден сделать этот матч, потому что он может законно лечить cat как «хвост» последовательности .+?.

Если йо якорь кошку в конце строки, то есть использовать ^(dog).+?(cat)?$, вы получите матч, хотя:

Pattern p = Pattern.compile("^(dog).+?(cat)?$"); 
for (String s : new String[] {"dog, cat", "dog, dog, cat", "dog, dog, dog"}) { 
    Matcher m = p.matcher(s); 
    if (m.find()) { 
     System.out.println(m.group(1)+" "+m.group(2)); 
    } 
} 

Печатает (demo 1)

dog cat 
dog cat 
dog null 

Do вы знаете, как с этим справиться, если есть что-то после кошки?

Вы можете иметь дело с ним, построив хитрее выражение, которое соответствует ничего, кроме cat, как это:

^(dog)(?:[^c]|c[^a]|ca[^t])+(cat)? 

Теперь cat может произойти в любом месте строки без анкера (demo 2).

+3

Спасибо. Вы случайно не знаете, как с этим справиться, если есть что-то после кошки? Например: «собака, собака, кошка, бла». Я хочу захватить только первую собаку и дополнительную кошку (может быть не больше одной кошки). – forsajt

+1

хотел бы увидеть этот ответ –

4

@ ответ dasblinkenlight является большим, но вот регулярное выражение, которое улучшает 2-ю часть, когда он/она попросила

ли вы не знаете, как бороться с ним в случае, если есть что-то после того, как кошка?

Регулятос ^(dog)(.+(cat))? потребует, что бы вы взяли номер группы. 3 вместо 2, чтобы получить дополнительную кошку, но работает так же хорошо, как и обманщик char-by-char.

И вот the demo (который, опять же, разветвляется от @ dasblinkenlight демоверсия, что позволило мне еще раз повозиться и найти это решение, спасибо!)

+0

Также работает с группой, не связанной с захватом, как^(собака) (?:. + (Cat))? поэтому у вас нет дополнительной группы захвата –

2

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

Используйте ?:, чтобы заключить в скобки часть регулярного выражения, которое не было захвачено. Таким образом, регулярное выражение становится следующим: ^(dog)(?:.+(cat))?

Снова, вот extended demo и regex test.

Смежные вопросы