¿Por qué String.split necesita delimitador de tubería para escapar?

140

Estoy tratando de analizar un archivo que tiene cada línea con valores delimitados por tuberías. No funcionó correctamente cuando no escapé del delimitador de tubería en el método de división, pero funcionó correctamente después de escapar de la tubería como se muestra a continuación.

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;
}

¿Alguien puede explicar por qué el carácter de la tubería debe escaparse para el split()método?

comenzar
fuente
13
Las respuestas a continuación respondieron el "por qué", pero solo para su información, si está tratando de hacer coincidir una cadena literal, también puede mirar Pattern.quote . Toma un Stringy devuelve una expresión regular Stringque coincidirá con la entrada (es decir, se encarga de todo el escape por usted).
yshavit
+1 paraPattern.quote
redDevil

Respuestas:

175

String.splitespera un argumento de expresión regular. Un no escapado |se analiza como una expresión regular que significa "cadena vacía o cadena vacía", que no es lo que quiere decir.

Louis Wasserman
fuente
76

Debido a que la sintaxis para que ese parámetro se divida es una expresión regular, donde en el '|' tiene un significado especial de OR, y un '\ |' significa un literal '|' entonces la cadena "\\ |" significa la expresión regular '\ |' lo que significa que coincide exactamente con el carácter '|'.

dlamblin
fuente
1
Gracias por esta explicación Casi siempre me olvido de usar el doble escape. Ahora que sé por qué es así, seguramente me ayudará a recordar de ahora en adelante.
sufinawaz
¿Qué sucede si el valor de la línea String tiene algunos caracteres Pipe? ¿Cómo podría dividir sin dividir la tubería escapada? ?
AlexandreJ
@AlexandreJ ¿Estás preguntando cómo dividir una línea que se parece a: Some|Delimited|Text|With|An\|Embedded|Pipe|Charen ("Some", "Delimited", "Text", "With", "An\|Embedded", "Pipe", "Char")? La función de división no admite el escape de esta manera, pero es posible que pueda crear una expresión regular que funcione para este caso, como con una afirmación negativa de ancho cero mirar detrás del grupo: (?<!\\)\|que seríaline.split("(?<!\\\\)\\|");
dlamblin
6

Simplemente puedes hacer esto:

String[] arrayString = yourString.split("\\|");
Ravinath
fuente
tienes que escapar de \ para usar eres regex "yourString.split (" \\ | ")" esa es la fórmula correcta.
mautrok