Java-8: сопоставление 1 шаблона несколько раз в 1 строке в файле (через фильтр) - PullRequest
0 голосов
/ 10 июня 2018

Имея этот файл данных:

    Test 1
    Test 2 Test 3 Test 11

Я хотел бы иметь программу, соответствующую каждому «Тесту (.)», Поэтому я получу вывод:

    Match: 1
    Match: 2
    Match: 3
    Match: 11

Программа ниже дает такой вывод:

    Match: 1

Программа:

void addMysteries( Path path, String output) {
    Pattern p = Pattern.compile(".?Test (.)");
    try (Stream<String> lines = Files.lines( path)) {
        lines.map( p::matcher)
                .filter(Matcher::matches)
                .forEach( matcher -> System.out.println("Match: " + matcher.group(1)));
    } catch( Exception e) {
        e.printStackTrace();
    }
}

В Java 7 , программное обеспечение ниже работает нормально.Почему это работает, а выше нет?

pattern = Pattern.compile(".?Test (.)");
input = "Test 1\n\rOtherStuff\nTest 2 Test 3";
matcher = pattern.matcher(input);
while (matcher.find()) {
    System.out.println(  "Match: " + matcher.group( 1));
}   

Ответы [ 2 ]

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

Это просто Test 2 Test 3 не соответствует регулярному выражению .?Test (.)

Вы можете добавить следующие flatMap перед map(p::matches), чтобы у вас были разбиты входные строки и по Test в каждомначало строки

.flatMap(x -> Arrays.stream(x.split(".?(?=Test)")))

Полный код

void addMysteries( Path path, String output) {
    Pattern p = Pattern.compile(".?Test (.)");
    try (Stream<String> lines = Files.lines( path)) {
        lines.flatMap(x -> Arrays.stream(x.split(".?(?=Test)")))
                .map( p::matcher)
                .filter(Matcher::matches)
                .forEach( matcher -> System.out.println("Match: " + matcher.group(1)));
    } catch( Exception e) {
        e.printStackTrace();
    }
}
0 голосов
/ 10 июня 2018

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

try (Stream<String> lines = Files.lines(path)) {
    lines.forEach(line ->
            {
                Matcher matcher = pattern.matcher(line);
                while (matcher.find()){
                    System.out.println("Match: " + matcher.group(1));
                }
            }
    );
} catch (Exception e) {
    e.printStackTrace();
}

Функции Java 9+

В Java 9+ вы можете использовать Matcher#results() во втором примере, поэтому это может быть:

Pattern pattern = Pattern.compile(".?Test (.)");
try (Stream<String> lines = Files.lines(path)) {
    lines.forEach(input -> pattern.matcher(input)
            .results()
            .forEach(matcher -> System.out.println("Match: " + matcher.group(1)))
    );
} catch (Exception e) {
    e.printStackTrace();
}

Или как @ Хольгер упомяните, что вы можете использовать flatMap с Matcher#results() примерно так:

try (Stream<String> lines = Files.lines(path)) {
    lines.flatMap(input ->
            pattern.matcher(input).results()
    ).forEach(matchResult -> System.out.println("Match: " + matchResult.group(1)));
} catch (IOException e) {
    e.printStackTrace();
}

Или даже вы можете прочитать весь файл, используя Сканер, где вы можете использовать Scanner::findAll, которые возвращают Поток вот так:

try (Scanner scanner = new Scanner(path)) {
    scanner.findAll(pattern).forEach(matchResult ->
            System.out.println("Match: " + matchResult.group(1))
    );
} catch (IOException e) {
    e.printStackTrace();
}

Выходы

Match: 1
Match: 2
Match: 3

Вы можете взглянуть на эти два обратных порта results() и findAll() @Holger:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...