Регулярное выражение не соответствует словам, разделенным пробелом - PullRequest
1 голос
/ 09 ноября 2011

У меня есть строка ввода, которая будет следовать шаблону /user/<id>?name=<name>, где <id> - буквенно-цифровой, но должен начинаться с буквы, а <name> - строка только из букв, которая может иметь несколько пробелов. Вот некоторые примеры совпадений:

/user/ad?name=a a
/user/one111?name=one ONE oNe
/user/hello?name=world

Я придумал следующее регулярное выражение:

String regex = "/user/[a-zA-Z]+\\w*\\?name=[a-zA-Z\\s]+";

Все приведенные выше примеры соответствуют регулярному выражению, но оно смотрит только на первое слово в <name>. Разве последовательность \s не должна позволять мне иметь пробелы?

Код, который я сделал, чтобы проверить, что он делает:

String regex = "/user/[a-zA-Z]+\\w*\\?name=[a-zA-Z\\s]+";
// Check to see that input matches pattern
if(Pattern.matches(regex, str) == true){
   str = str.replaceFirst("/user/", "");
   str = str.replaceFirst("name=", "");
   String[] tokens = str.split("\\?");
   System.out.println("size = " + tokens.length);
   System.out.println("tokens[0] = " + tokens[0]);
   System.out.println("tokens[1] = " + tokens[1]);
} else
    System.out.println("Didn't match.");

Так, например, один тест может выглядеть так:

/user/myID123?name=firstName LastName
size = 2
tokens[0] = myID123
tokens[1] = firstName

, тогда как желаемый результат будет

tokens[1] = firstName LastName

Как я могу изменить свое регулярное выражение, чтобы сделать это?

Ответы [ 3 ]

3 голосов
/ 09 ноября 2011

Не уверен, что, по вашему мнению, является проблемой в вашем коде. tokens[1] будет действительно содержать firstName LastName в вашем примере.

Вот демоверсия ideone.com , показывающая это.


Однако рассматривали ли вы возможность использования групп захвата для идентификатора и имени.

Если вы напишите это как

String regex = "/user/(\\w+)\\?name=([a-zA-Z\\s]+)";

Matcher m = Pattern.compile(regex).matcher(input);

вы можете получить от myID123 и firstName LastName до m.group(1) и m.group(2)

1 голос
/ 09 ноября 2011

Проблема в том, что * по умолчанию жадный (соответствует всей строке), поэтому вам нужно изменить свое регулярное выражение, добавив ? (что делает его неохотным):

    List<String> str = Arrays.asList("/user/ad?name=a a", "/user/one111?name=one ONE oNe", "/user/hello?name=world");
    String regex = "/user/([a-zA-Z]+\\w*?)\\?name=([a-zA-Z\\s]+)";

    for (String s : str) {
        Matcher matcher = Pattern.compile(regex).matcher(s);
        if (matcher.matches()) {
            System.out.println("user: " + matcher.group(1));
            System.out.println("name: " + matcher.group(2));
        }
    }

Выход:

user: ad
name: a a
user: one111
name: one ONE oNe
user: hello
name: world
1 голос
/ 09 ноября 2011

Я не нахожу ошибок в вашем коде, но вы можете захватить группу следующим образом:

    String str = "/user/myID123?name=firstName LastName ";      
    String regex = "/user/([a-zA-Z]+\\w*)\\?name=([a-zA-Z\\s]+)";
    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher(str);
    if(m.find()) {
        System.out.println(m.group(1) + ", " + m.group(2));
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...