Группа захвата Regex не распознает группу (1), несмотря на совпадения () true

1

Я пишу несколько простых (я думал) регулярных выражений в Java, чтобы удалить звездочку или амперсанд, которая встречается непосредственно рядом с некоторой определенной пунктуацией.
Это был мой оригинальный код:

String ptr = "\\s*[\\*&]+\\s*";
String punct1 = "[,;=\\{}\\[\\]\\)]"; //need two because bracket rules different for ptr to left or right
String punct2 = "[,;=\\{}\\[\\]\\(]";

out = out.replaceAll(ptr+"("+punct1+")|("+punct2+")"+ptr,"$1");

Который вместо того, чтобы просто удалять часть "ptr" строки, также удалил punct! (т.е. заменили строку с нулевой строкой)
Я дополнительно изучил:

String ptrStr = ".*"+ptr+"("+punct1+")"+".*|.*("+punct2+")"+ptr+".*";
Matcher m_ptrStr = Pattern.compile(ptrStr).matcher(out);

и обнаружил, что:

m_ptrStr.matches() //returns true, but...
m_ptrStr.group(1) //returns null??

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

Теги:
capturing-group

2 ответа

2
Лучший ответ

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

(regex1)|(regex2)

Соединитель начнет и начнет поиск, используя первое чередование; если не найден, он попробует второе чередование.

Тем не менее, это все еще две группы, и только один будет соответствовать. Тот, который не будет соответствовать, вернет null, и это то, что происходит с вами здесь.

Поэтому вам необходимо проверить обе группы; поскольку у вас есть совпадение, по крайней мере одно не будет равно нулю.

  • 0
    Да, извините ... Я привык пересматривать языки, где это не повод для беспокойства: /
1

Когда у вас есть | в вашем шаблоне, это означает, что совпадению разрешено соответствовать одному из двух шаблонов. Каким бы ни был он, любые группы захвата для шаблона, который он соответствует, вернут подстроки, но любые группы захвата для другого шаблона возвращают значение null, потому что другой шаблон не был действительно сопоставлен.

Похоже, ваш шаблон

.*\s*[\*&]+\s*([,;=\{}\[\]\)]).*|.*([,;=\{}\[\]\(])+\s*[\*&]+\s*.*
------------- left ------------- -------------- right ------------

Если matches() возвращает true, то ваша строка соответствует шаблону "left", и в этом случае group(1) будет не нулевой, а group(2) будет равна null; или же он соответствует "правильному" шаблону, и в этом случае group(1) будет нулевой, а group(2) не равна нулю. [Примечание. Матч не будет пытаться выяснить, успешны ли обе стороны. То есть, если левая сторона соответствует, она не будет проверять правильную сторону.]

  • 1
    «Сопоставитель не будет проверять, соответствует ли он обеим сторонам» <- не совсем; он попробует второе чередование, если первое не удастся. Механизмы регулярных выражений POSIX (которых нет в Java) всегда будут проверять оба варианта, как и механизмы DFA
  • 0
    @fge Я не имел в виду случай, когда первая альтернатива не удалась, но я попытался уточнить формулировку. Интересный (и удивительный) тидбит о других движках регулярных выражений - спасибо.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню