Por que o String.split precisa que o delimitador de canal seja escapado?

140

Estou tentando analisar um arquivo que tem cada linha com valores delimitados por canal. Ele não funcionou corretamente quando eu não escapei do delimitador de tubos no método de divisão, mas funcionou corretamente depois que eu escapei do tubo, como abaixo.

private ArrayList<String> parseLine(String line) {
    ArrayList<String> list = new ArrayList<String>();
    String[] list_str = line.split("\\|"); // note the escape "\\" here
    System.out.println(list_str.length);
    System.out.println(line);
    for(String s:list_str) {
        list.add(s);
        System.out.print(s+ "|");
    }
    return list;
}

Alguém pode explicar por que o caractere de pipe precisa ser escapado para o split()método?

starthis
fonte
13
As respostas abaixo responderam o "porquê", mas apenas para sua informação, se você estiver tentando corresponder a uma String literal, também poderá consultar Pattern.quote . Ele pega um Stringe retorna um regex Stringque corresponderá à entrada (ou seja, ele cuida de todos os escapes para você).
precisa saber é
+1 paraPattern.quote
redDevil

Respostas:

175

String.splitespera um argumento de expressão regular. Um sem escape |é analisado como uma expressão regular que significa "sequência vazia ou sequência vazia", ​​que não é o que você quer dizer.

Louis Wasserman
fonte
76

Como a sintaxe para esse parâmetro ser dividido é uma expressão regular, onde no '|' tem um significado especial de OR e um '\ |' significa um literal '|' então a string "\\ |" significa a expressão regular '\ |' o que significa corresponder exatamente ao caractere '|'.

dlamblin
fonte
1
Obrigado por esta explicação. Quase sempre esqueço de usar a fuga dupla. Agora que sei por que é assim, certamente me ajudará a lembrar de agora em diante.
sufinawaz
O que acontece se o valor da linha String tiver alguns caracteres Pipe? Como você seria capaz de dividir sem dividir o tubo de escape \ | ?
AlexandreJ
@AlexandreJ Você está perguntando como dividir uma linha que se parece com: Some|Delimited|Text|With|An\|Embedded|Pipe|Charinto ("Some", "Delimited", "Text", "With", "An\|Embedded", "Pipe", "Char")? A função split não suporta escape assim, mas você pode criar uma expressão regular que funcione neste caso, como com uma asserção negativa de largura zero, por trás do grupo: o (?<!\\)\|que serialine.split("(?<!\\\\)\\|");
dlamblin
6

Você pode simplesmente fazer isso:

String[] arrayString = yourString.split("\\|");
Ravinath
fonte
você precisa escapar do \ para usar sua expressão regular "yourString.split (" \\ | ")", que é a fórmula correta.
Mautrok