Почему "привет \ мир *" не соответствует "привет миру"? - PullRequest
9 голосов
/ 10 июня 2011

Почему этот код генерирует исключение InputMismatchException?

Scanner scanner = new Scanner("hello world");
System.out.println(scanner.next("hello\\s*world"));

То же совпадение с регулярным выражением в http://regexpal.com/ (с \ s вместо \\ s)

Ответы [ 5 ]

11 голосов
/ 10 июня 2011

Сканер, в отличие от Matcher, имеет встроенную токенизацию строки, разделителем по умолчанию является пробел. Таким образом, ваш «привет мир» становится токенизированным в «привет» «мир» до начала матча. Было бы совпадение, если вы изменили разделитель перед сканированием на что-то, что не находится в строке, например ::

Scanner scanner = new Scanner("hello world");
scanner.useDelimiter(":");
System.out.println(scanner.next("hello\\s*world"));

но, похоже, действительно для вашего случая вы должны просто использовать Matcher.

Это пример использования сканера «по назначению»:

   Scanner scanner = new Scanner("hello,world,goodnight,moon");
   scanner.useDelimiter(",");
   while (scanner.hasNext()) {
     System.out.println(scanner.next("\\w*"));
   }

вывод будет

hello
world
goodnight
moon
2 голосов
/ 10 июня 2011

Эти входы работают:

"C:\Program Files\Java\jdk1.6.0_21\bin\java"  RegexTest hello\s+world "hello      world"
'hello      world' does match 'hello\s+world'

Вот код:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexTest {

    public static void main(String[] args) {

        if (args.length > 0) {
            Pattern pattern = Pattern.compile(args[0]);

            for (int i = 1; i < args.length; ++i) {
                Matcher matcher = pattern.matcher(args[i]);
                System.out.println("'" + args[i] + "' does " + (matcher.matches() ? "" : "not ") + "match '" + args[0]  +"'");
            }
        }
    }

}
2 голосов
/ 10 июня 2011

Разделителем по умолчанию для сканера являются пробелы, поэтому сканер видит два элемента hello и world hello \ s + world не соответствует hello, поэтому выдается исключение NoSuchElement.

1 голос
/ 10 июня 2011

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

Scanner # next возвращает следующий токен, если он соответствует данному шаблону.Другими словами, шаблон, который вы передаете в #next, может не содержать пробелов по умолчанию.

Вы можете вызвать #useDelimiter для настройки сканера для вашего варианта использования.

0 голосов
/ 10 июня 2011

Сканер имеет разделитель по умолчанию \\s+ Если вы хотите сопоставить только hello\\s*world, просто позвоните scanner.useDelimiter("hello\\s*world")), а затем просто scanner.next();

Альтернативно, вы можете позвонить scanner.useDelimiter('any (escaped) char that would not occur in your text ') и использовать scanner.next("hello\\s*world"))

В качестве примечания: если вы хотите, чтобы он имел хотя бы 1 пробел, вы хотите использовать + вместо *

...