Поиск номера после определенного слова, которое не предшествует непосредственно номеру - PullRequest
0 голосов
/ 05 июля 2018

Я пытаюсь использовать шаблон для поиска почтового индекса в строке. Я не могу заставить его работать правильно.

Пример строки ввода

What is the weather in 75042?

Я пытаюсь использовать шаблон

public String getZipcode(String inputLine) {

        Pattern pattern = Pattern.compile(".*weather.*([0-9]+).*");
        Matcher matcher = pattern.matcher(inputLine);

        if (matcher.find()) {

            return matcher.group(1).toString();
        }

        return "Zipcode Not Found.";

    }

Если я хочу получить только 75002, что мне нужно изменить? Это выводит только последнюю цифру числа 2. Я ужасно смущен и не до конца понимаю Javadocs для класса Pattern.

Ответы [ 6 ]

0 голосов
/ 05 июля 2018

В регулярных выражениях операторы без верхней границы (*, +) имеют вид жадный .

Были уже предложены идеальные решения. Я просто добавляю тот, который очень близок к вашему и решает проблему более изолированным способом:

Если вы используете регулярное выражение

".*weather.*?([0-9]+).*" ... вместо ...

".*weather.*([0-9]+).*"

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

Жадность означает использование максимально возможного количества символов (слева направо), в то же время позволяя сопоставить оставшуюся часть регулярного выражения.

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

0 голосов
/ 05 июля 2018

Проблема в том, что ваш средний .* слишком жадный и съедает 7500. Одно простое решение - добавить пробел перед вашим регулярным выражением: .*weather.* ([0-9]+).* или даже использовать \\s. Но лучше всего использовать не жадную версию .*?, поэтому регулярное выражение должно быть .*weather.*?([0-9]+).*

0 голосов
/ 05 июля 2018

Я думаю, все, что вам нужно, это \\d+

public String getZipcode(String inputLine) throws Exception {

    Pattern pattern = Pattern.compile("\\d+");
    Matcher matcher = pattern.matcher(inputLine);

    if (matcher.find()) {
        return matcher.group();
    }

    //A good practice is to throw an exception if no result found
    throw new NoSuchElementException("Zipcode Not Found.");

}
0 голосов
/ 05 июля 2018

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

Здесь можно использовать более простой шаблон: \D+(\d+)\D+, что означает

  • некоторые не цифры \D+, затем несколько цифр для захвата (\d+), затем некоторые не цифры \D+
public String getZipcode(String inputLine) {
    Pattern pattern = Pattern.compile("\\D+(\\d+)\\D+");
    Matcher matcher = pattern.matcher(inputLine);

    if (matcher.find()) {
        return matcher.group(1).toString();
    }
    return "Zipcode Not Found.";
}

Workable Demo

0 голосов
/ 05 июля 2018

Пробелы в вашем регулярном выражении отсутствуют (\ s). Вы можете использовать \ s * или \ s + на основе ваших данных

Pattern pattern = Pattern.compile("weather\\s*\\w+\\s*(\\d+)");
Matcher matcher = pattern.matcher(inputLine);
0 голосов
/ 05 июля 2018

Ваш шаблон .*weather.*([0-9]+).* захватывает всю строку с первым .* и возвращает назад, чтобы найти weather, и, если он находит его, он захватывает часть строки после слов до конца строки с последующим .* образец и возврат назад, чтобы найти последнюю цифру, и единственная цифра сохраняется в группе захвата 1, так как одна цифра удовлетворяет шаблону [0-9]+. Последний .* просто потребляет строку до конца.

Вы можете решить проблему, просто используя ".*weather.*?([0-9]+).*" (делая второй .* ленивым), но поскольку вы используете Matcher#find(), вы можете использовать более простое регулярное выражение:

Pattern pattern = Pattern.compile("weather\\D*(\\d+)");

И после получения совпадения получить значение с помощью matcher.group(1).

См. regex demo .

Детали шаблона

  • weather - weather слово
  • \\D* - 0+ символов, кроме цифр
  • (\\d+) - Группа захвата 1: одна или несколько цифр

См. Демонстрационную версию Java :

String inputLine = "What is the weather in 75042?";
Pattern pattern = Pattern.compile("weather\\D*(\\d+)");
Matcher matcher = pattern.matcher(inputLine);

if (matcher.find()) {
    System.out.println(matcher.group(1)); // => 75042
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...