Я пишу простое (как мне казалось) регулярное выражение на 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», удалила и точку! (т.е. заменил совпавшую строку пустой строкой)
Я проверил дальше, выполнив:

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??

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

1
Magg G. 19 Мар 2014 в 19:34

2 ответа

Лучший ответ

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

(regex1)|(regex2)

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

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

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

2
fge 19 Мар 2014 в 15:49

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

Похоже, ваш узор

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

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

1
ajb 19 Мар 2014 в 16:07