Регулярное выражение Java два вопросительных знака (??)
Я знаю, что /? означает, что / является необязательным. Итак " игрушки?"будет соответствовать как игрушке, так и игрушкам. Я понимаю, что если я сделаю его ленивым и использую "игрушки??"Я буду соответствовать и игрушке и игрушкам и всегда возвращать игрушку. Итак, быстрый тест:
private final static Pattern TEST_PATTERN = Pattern.compile("toys??", Pattern.CASE_INSENSITIVE);
public static void main(String[] args) {
for(String arg : args) {
Matcher m = TEST_PATTERN.matcher(arg);
System.out.print("Arg: " + arg);
boolean b = false;
while (m.find()) {
System.out.print(" {");
for (int i=0; i<=m.groupCount(); ++i) {
System.out.print("[" + m.group(i) + "]");
}
System.out.print("}");
}
System.out.println();
}
}
Да, похоже, он работает так, как ожидалось
java -cp .. regextest.RegExTest toy toys
Arg: toy {[toy]}
Arg: toys {[toy]}
теперь измените регулярное выражение на " игрушки??2 " и он по-прежнему соответствует toys2 и toy2. В обоих случаях он возвращает всю строку без удаления s. Есть ли какие-либо функциональные разница между поиском " игрушек?2" и "игрушки??2".
причина, по которой я спрашиваю, заключается в том, что я нашел пример, подобный следующему:
private final static Pattern TEST_PATTERN = Pattern.compile("</??tag(s+?.*?)??>", Pattern.CASE_INSENSITIVE);
и хотя я не вижу очевидной причины для использования ?? чем ? Я подумал, что, возможно, первоначальный автор (который мне неизвестен) может знать что-то, чего я не знаю, я ожидаю позже.
1 ответов
??
лентяй, а ?
жаден.
дано (pattern)??
, он сначала проверит пустую строку, а затем, если остальная часть шаблона не может совпадать, он будет проверять pattern
.
в противоположность (pattern)?
будет проверить для pattern
во-первых, затем он будет проверять пустую строку на backtrack.
теперь измените регулярное выражение на " игрушки??2 " и он по-прежнему соответствует toys2 и toy2. В обоих случаях он возвращает всю строку без s удален. Есть ли функциональная разница между поиском "игрушек"?2" и "игрушки??2".
разница в порядке поиска:
-
"toys?2"
ищетtoys2
, потомtoy2
-
"toys??2"
ищетtoy2
, потомtoys2
но для случая этих 2 шаблонов результат будет одинаковым независимо от входной строки, так как продолжение 2
(после s?
или s??
) должно быть совпадение.
что касается шаблона, который вы нашли:
Pattern.compile("</??tag(\s+?.*?)??>", Pattern.CASE_INSENSITIVE)
и ??
можно изменить на ?
не влияя на результат:
-
/
иt
(intag
) составляют взаимоисключающие. Вы либо одно, либо другое. -
>
и\s
также взаимоисключающие. По крайней мере, 1 в\s+?
важно для этого вывода: результат может быть другой иначе.
это, вероятно, микро-оптимизация от автора. Он, вероятно, думает, что открытый тег должен быть там, в то время как закрывающий тег может быть забыт, и что открытые/закрытые теги без атрибутов/случайных пространств появляются чаще, чем у некоторых.
кстати, двигатель может столкнуться с какой-то дорогой попыткой возврата из-за \s+?.*?
когда вход имеет <tag
затем много пробелов без >
в любом месте рядом.