2015-11-21 3 views
2

я нашел разницу, но я не могу это объяснить:Компиляция шаблона. *? . * Против

public static void main(String[] args) { 
    Pattern p = Pattern.compile("[+-]?\\d+.*?"); 
    Matcher m = p.matcher("+5.0h"); 
    System.out.println(m.matches());         //prints true 

    Scanner in = new Scanner("+5.0h"); 
    while (in.hasNext()) { 
     if (in.hasNext(p)) { 
      System.out.println(in.findInLine(p));      //prints +5 
     } 
    } 
    in.close(); 

    System.out.println("6.0hgf".matches("[+-]?\\d+.*?")); //prints nothing,it seemed that this sentence didn't execute,why this happened? 
} 

, когда я изменил

Pattern p = Pattern.compile("[+-]?\\d+.*?") 

в

Pattern p = Pattern.compile("[+-]?\\d+.*") 

произошло следующее:

public static void main(String[] args) { 
    Pattern p = Pattern.compile("[+-]?\\d+.*"); 
    Matcher m = p.matcher("+5.0h"); 
    System.out.println(m.matches());         //prints true 

    Scanner in = new Scanner("+5.0h"); 
    while (in.hasNext()) { 
     if (in.hasNext(p)) { 
      System.out.println(in.findInLine(p));      //prints +5.0h 
     } 
    } 
    in.close(); 

    System.out.println("6.0hgf".matches("[+-]?\\d+.*?")); //prints true 
} 

, поэтому я хотел бы знать, почему это произошло?

+0

Возможно, последняя строка второго примера неверна. Это то же самое, что и в первом примере. Таким образом, результат печати не может быть другим! – CoronA

ответ

0

.* потребляет столько же символов, как достаточно, чтобы соответствовать (жадный)

.*? потребляет наименьшее количество символов, как достаточно, чтобы соответствовать

Ваш первый пример соответствие целое слово:

Matcher m = p.matcher("+5.0h"); 
System.out.println(m.matches()); 

Это означает, что дано совпадение, и нет места для разных чисел совпадающих символов.

Следующий пример пытается найти закономерность:

in.findInLine(p) 

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

Последний пример не воспроизводится для меня: true в обоих случаях.

1

Ну, . любых символы (явно не десятичная точка), а затем у вас есть, если следует две разных вещей, * который является жадным квантором ноля или более раз и *? который неохотно квантор для того же предмет (см. Differences Among Greedy, Reluctant, and Possessive Quantifiers).

То, что нехотя версия "[+-]?\\d+.*?" позволяет прочитать +, чтобы найти матч и находит его с одной или несколькими цифрами (с жадностью). Затем он ищет любой символ 0 или более раз и находит совпадение с использованием любого символа 0 раз (поэтому конечный .*? по существу бессмыслен).

Жадная версия "[+-]?\\d+.*" запускается аналогичным образом, позволяя +, чтобы найти соответствие с цифрами; но затем поглощает все персонажи, которые он может получить, что, конечно же, остальное.


Наконец, ошибка в первой версии (с использованием "[+-]?\\d+.*?") вытекает из того, как вы используете hasNext(String pattern) метод Сканера, который является сравнение следующего маркера. Так как первая итерация удаляет "+5" следующий маркер оставшегося ".0h", условия затем оценить следующим образом:

while (in.hasNext()) { //true, we have ".0h" 
    if (in.hasNext(p)) { //false, ".0h" does not begin with +,-, or digit 
     System.out.println(in.findInLine(p)); //no longer called, scanner doesn't advance 
    } 
} 

Поэтому, естественно, линия после цикла никогда не достигается.

Для сравнения, в жадной версии (с использованием «[+ -]? \ D +. *») Первая итерация in.findInLine(p) принимает всю строку, поэтому теперь in.hasNext() является ложным и цикл завершается.

+0

Возможно, вы пропустили System.out.println ("6.0hgf" .matches ("[+ -]? \\ d +. *?")); // ничего не печатает, казалось, что это предложение не выполнялось, почему это произошло? в первом случае, в моем затмении, это произошло, и я не знаю, почему –

+0

Линия сама по себе не ошибается. Что вы имеете в виду при первом броске, это произошло? – Linus

+0

Я имею в виду, что ничего не было напечатано. Теперь я выяснил, что должен быть разрыв во время цикла, поэтому я добавил еще разрыва в цикл while, а затем программа выполнила правильно. Спасибо за ответ. –

1

Поведение * по умолчанию должно соответствовать как можно большему количеству, помещая ? после того, как оно будет соответствовать только столько, сколько необходимо.

напр:

, если у меня есть строка "abc" и я использую .*, он будет соответствовать всей строке, но если я изменить регулярное выражение .*? это ничего не соответствует, потому что * является 0 или больше.

Мы также можем взять пример + где, если строка является снова "abc" и регулярное выражение .+ будет соответствовать всей строке, но если регулярное выражение .+? это будет соответствовать только один символ, в данном случае a.

0

Другие ответы объяснили разницу между .* и .*?. Чтобы ответить на другой вопрос, почему не System.out.println выполнить в первом случае: Проблема с вашей петлей:

while (in.hasNext()) { 
    if (in.hasNext(p)) { 
     System.out.println(in.findInLine(p));     //prints +5 
    } 
} 

Если есть больше данных сканирования, но это не соответствует шаблону, это является бесконечным циклом. Ничего не будет потреблено, и код будет продолжать проверять hasNext() и hasNext(p) на один и тот же текст ввода, снова и снова. Поэтому вам нужно переосмыслить, что вы хотите, чтобы ваш код делал, если он не может соответствовать шаблону.

Причина, по которой это не произошло, когда вы использовали .*, состоит в том, что .* заставлял остальную часть ввода забираться. Это означало, что in.hasNext() вернул false в следующий раз, потому что больше не было ввода.