Mając zdanie z wieloma spacjami za pomocą wyrażenia regularnego, staram się osiągnąć następujące rezultaty:

Przykład zdania: To jest prosty tekst.

Oczekiwany wynik : [This,     is, a, simple, text.]

Rzeczywisty wynik : [This, is, a, simple, text.]

ArrayList<String> tokens = new ArrayList<>();
Pattern tokSplitter = Pattern.compile("[a-zA-Z.*//s*]+");
Matcher m = tokSplitter.matcher("This     is a simple text.");
    while (m.find()) {
            tokens.add(m.group());
    }
    System.out.println(tokens);
2
makhlo 31 marzec 2020, 18:25

4 odpowiedzi

Najlepsza odpowiedź

Możesz napisać coś takiego:

public static void main(String[] args) {
    ArrayList<String> tokens = new ArrayList<>();
    Pattern tokSplitter = Pattern.compile("(\\s*[a-zA-Z.]+)\\s?");
    Matcher m = tokSplitter.matcher("This     is a simple text.");
    while (m.find()) {
        tokens.add(m.group(1));
    }
    System.out.println(tokens);
}

Się: [This, is, a, simple, text.]

2
User9123 31 marzec 2020, 15:54

Oto prosty wzór rozwiązania zadania: \s*\S+

Demo.

Kod będzie wyglądał następująco:

ArrayList<String> tokens = new ArrayList<>();
Pattern tokSplitter = Pattern.compile("\\s*\\S+");
Matcher m = tokSplitter.matcher("This     is a simple text.");
    while (m.find()) {
            tokens.add(m.group());
    }
    System.out.println(tokens);
1
kishkin 31 marzec 2020, 17:56

Używasz niewłaściwego narzędzia do pracy. Jeśli chcesz podzielić ciąg, użyj operacji split:

List<String> tokens = Arrays.asList("This     is a simple text.".split("\\b "));

Tworzy listę o tej samej treści, co aktualnie akceptowana odpowiedź. Warto zauważyć, że oba rozwiązania zajmują jedną spację ograniczającą i zachowują tylko dodatkowe spacje, podczas gdy wyjście System.out.println(tokens); to [This, is, a, simple, text.], ponieważ metoda toString() wszystkich standardowych implementacji List wstawia spację po każdym przecinku.

Jeśli chcesz zachować wszystkie spacje, musisz użyć

List<String> tokens = Arrays.asList("This     is a simple text.".split("\\b(?= )"));

Zamiast. Rzeczywiste ciągi wynikowe można zobaczyć, używając:

tokens.forEach(s -> System.out.println('"'+s+'"'));
"This"
"     is"
" a"
" simple"
" text."

W porównaniu do

"This"
"    is"
"a"
"simple"
"text."

Pozostałych rozwiązań.

Jeśli chcesz bezpośrednio załatwić sprawę Pattern, np. aby móc go ponownie użyć, nadal nie powstrzymuje Cię to przed użyciem split zamiast pętli dopasowań:

Pattern wordEnd = Pattern.compile("\\b(?= )");
List<String> tokens = Arrays.asList(wordEnd.split("This     is a simple text."));
tokens.forEach(s -> System.out.println('"'+s+'"'));
2
Holger 1 kwiecień 2020, 10:31

Myślę, że użycie lookaround to najprostszy sposób rozwiązania problemu.

Pattern tokSplitter = Pattern.compile("(?<=\\S)\\s");
String str = "This     is a simple text.";
ArrayList<String> tokens = Arrays.asList(tokSplitter.split(str));
System.out.println(tokens);
2
NullPointerException 31 marzec 2020, 16:06