Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apply pattern on file stream

public final Pattern PATTERN = Pattern.compile("<abc:c\\sabc:name=\"(\\S+)\"\\sabc:type=\"(\\S+)\">");
    try (Stream<String> stream = Files.lines(template.getPath())) {
        stream.filter(s -> PATTERN.matcher(s).find()).forEach(System.out::println);

    } catch (IOException e) {
        e.printStackTrace();
    }

The pattern works fine but how can I catch/get my groups? At the moment I get only Strings.

like image 253
Tobias Avatar asked Jan 28 '16 15:01

Tobias


1 Answers

If the pattern you're applying only appears one time for a line, you can map your Stream<String> into a Stream<Matcher>, filter the lines that matches the pattern and finally extract the group 1 and 2 by storing them in an array.

try (Stream<String> stream = Files.lines(Paths.get(""))) {
    stream.map(PATTERN::matcher)
          .filter(Matcher::find)
          .map(m -> new String[] { m.group(1), m.group(2) })
          .forEach(a -> System.out.println(Arrays.toString(a)));
} catch (IOException e) {
    e.printStackTrace();
}

If the pattern appears more than one time, we would need to loop over the Matcher until find() returns false. In this case, we could have

try (Stream<String> stream = Files.lines(Paths.get(""))) {
    stream.map(PATTERN::matcher)
          .flatMap(m -> {
              List<String[]> list = new ArrayList<>();
              while (m.find()) {
                  list.add(new String[] { m.group(1), m.group(2) });
              }
              return list.stream();
          })
          .forEach(a -> System.out.println(Arrays.toString(a)));

In Java 9, there may be a new method Matcher.results() to retrieve a Stream<MatchResult> of the results. We could use it here instead of having 2 separate find and group operations.

like image 86
Tunaki Avatar answered Oct 25 '22 09:10

Tunaki