Это сложный вопрос, и, возможно, в итоге у него нет решения (или, по крайней мере, не разумного). Я хотел бы иметь конкретный пример Java, но если это можно сделать, я думаю, что я мог бы сделать это с любым примером.
Моя цель - найти способ узнать, может ли строка, читаемая из входного потока, по-прежнему соответствовать заданному шаблону регулярного выражения. Или, другими словами, читайте поток до тех пор, пока мы не получим строку, которая определенно не будет соответствовать такому шаблону, независимо от того, сколько символов вы добавите к нему.
Объявление минималистского простого метода для достижения этой цели может выглядеть примерно так:
boolean couldMatch(CharSequence charsSoFar, Pattern pattern);
Такой метод вернул бы true
в случае, если charsSoFar
все еще может соответствовать шаблону, если добавлены новые символы, или false
, если у него вообще нет шансов сопоставить его даже с добавлением новых символов.
Чтобы привести более конкретный пример, скажем, у нас есть шаблон для чисел с плавающей точкой, например "^([+-]?\\d*\\.?\\d*)$"
.
При таком шаблоне couldMatch
вернет true
для следующего примера charsSoFar
параметр:
"+"
"-"
"123"
".24"
"-1.04"
И так далее, и тому подобное, потому что вы можете продолжать добавлять цифры ко всем этим, а также одну точку в трех первых.
С другой стороны, все эти примеры, полученные из предыдущего, должны возвращать false
:
"+A"
"-B"
"123z"
".24."
"-1.04+"
На первый взгляд ясно, что они никогда не будут соответствовать вышеупомянутому шаблону, независимо от того, сколько символов вы добавите к нему.
EDIT:
Я добавляю свой текущий подход без регулярных выражений прямо сейчас, чтобы прояснить ситуацию.
Сначала я объявляю следующий функциональный интерфейс:
public interface Matcher {
/**
* It will return the matching part of "source" if any.
*
* @param source
* @return
*/
CharSequence match(CharSequence source);
}
Тогда предыдущая функция будет переопределена как:
boolean couldMatch(CharSequence charsSoFar, Matcher matcher);
И (составленный) метод сопоставления для чисел с плавающей запятой может выглядеть следующим образом (обратите внимание, что в начале не поддерживается знак +, только -):
public class FloatMatcher implements Matcher {
@Override
public CharSequence match(CharSequence source) {
StringBuilder rtn = new StringBuilder();
if (source.length() == 0)
return "";
if ("0123456789-.".indexOf(source.charAt(0)) != -1 ) {
rtn.append(source.charAt(0));
}
boolean gotDot = false;
for (int i = 1; i < source.length(); i++) {
if (gotDot) {
if ("0123456789".indexOf(source.charAt(i)) != -1) {
rtn.append(source.charAt(i));
} else
return rtn.toString();
} else if (".0123456789".indexOf(source.charAt(i)) != -1) {
rtn.append(source.charAt(i));
if (source.charAt(i) == '.')
gotDot = true;
} else {
return rtn.toString();
}
}
return rtn.toString();
}
}
Внутри пропущенного тела для метода mightMatch он просто будет итеративно вызывать matcher.match () с новым символом, добавленным в конце параметра источника, и возвращать истину, в то время как возвращенный CharSequence равен параметру источника, и ложь как только все по-другому (это означает, что последний добавленный символ сломал матч).