Ответ 1
Я думаю, вы должны использовать парсер, а не простые регулярные выражения.
Регулярные выражения хороши, обеспечивая совпадения строк, но не совсем так, предоставляя NON-match, не говоря уже о том, почему совпадение не удалось.
Я использую регулярное выражение для соответствия тому, соответствует ли шаблон, но я также хочу знать, когда он терпит неудачу.
Например, скажем, у меня есть шаблон "N {1,3} Y". Я сопоставляю его со строкой "NNNNY". Я хотел бы знать, что он потерпел неудачу, потому что было слишком много Ns. Или, если я сопоставляю его со строкой "XNNY", я хотел бы знать, что она потерпела неудачу, потому что в строке был недопустимый символ "X".
От взгляда на API Java регулярного выражения (java.util.regex) дополнительная информация только кажется доступной из класса Matcher, когда совпадение выполнено успешно.
Есть ли способ решить эту проблему? Или это регулярное выражение даже в этом сценарии?
Я думаю, вы должны использовать парсер, а не простые регулярные выражения.
Регулярные выражения хороши, обеспечивая совпадения строк, но не совсем так, предоставляя NON-match, не говоря уже о том, почему совпадение не удалось.
То, о чем вы просите, потребует, чтобы синтаксический анализатор определял ближайшую строку, которая фактически соответствует вашему выражению. Это нетривиальная проблема, которая, вероятно, будет выполняться в экспоненциальном времени (например, поиск всех возможных строк одинаковой длины, чтобы найти совпадение.)
Итак, короче говоря, нет.
Это может сработать, но я не знаю, так ли оно вам нужно.
Когда вы используете matches
, он терпит неудачу, если вся последовательность не соответствует, но вы все равно можете использовать find
, чтобы увидеть, содержит ли остальная часть последовательности шаблон и, таким образом, понять, почему это не удалось:
import java.util.regex.*;
import static java.lang.System.out;
class F {
public static void main( String ... args ) {
String input = args[0];
String re = "N{1,3}Y";
Pattern p = Pattern.compile(re);
Matcher m = p.matcher(input);
out.printf("Evaluating: %s on %s%nMatched: %s%n", re, input, m.matches() );
for( int i = 0 ; i < input.length() ; i++ ) {
out.println();
boolean found = m.find(i);
if( !found ) {
continue;
}
int s = m.start();
int e = m.end();
i = s;
out.printf("m.start[%s]%n"
+"m.end[%s]%n"
+"%s[%s]%s%n",s,e,
input.substring(0,s),
input.substring(s,e),
input.substring(e) );
}
}
}
Вывод:
C:\Users\oreyes\java\re>java F NNNNY
Evaluating: N{1,3}Y on NNNNY
Matched: false
m.start[1]
m.end[5]
N[NNNY]
m.start[2]
m.end[5]
NN[NNY]
m.start[3]
m.end[5]
NNN[NY]
C:\Users\oreyes\java\re>java F XNNY
Evaluating: N{1,3}Y on XNNY
Matched: false
m.start[1]
m.end[4]
X[NNY]
m.start[2]
m.end[4]
XN[NY]
В первом выводе: N[NNNY]
вы можете указать там, где слишком много N, во втором: X[NNY]
присутствовал X.
Здесь другой выход
C:\Users\oreyes\java\re>java F NYXNNXNNNNYX
Evaluating: N{1,3}Y on NYXNNXNNNNYX
Matched: false
m.start[0]
m.end[2]
[NY]XNNXNNNNYX
m.start[7]
m.end[11]
NYXNNXN[NNNY]X
m.start[8]
m.end[11]
NYXNNXNN[NNY]X
m.start[9]
m.end[11]
NYXNNXNNN[NY]X
Шаблон существует, но все выражение не совпадает.
Немного сложно понять, как найти, сопоставить и посмотреть на работы из документа (по крайней мере, это произошло со мной), но я надеюсь, что этот пример поможет вам разобраться.
совпадение похоже на /^YOURPATTERNHERE$/
lookAt похоже на /^YOURPATTERNHERE/
find похож на /YOURPATTERNHERE/
Надеюсь, это поможет.
Для простых выражений типа "N {1,3} Y" вы найдете решение без инструментов самостоятельно. Но для более сложных выражений мой опыт подсказывает: