regulares regular probar palabra online expresiones expresion exacta espacio ejemplos crear blanco alfanumerico java regex preg-match string-split

regular - java split



Expresión regular a Split String en función del espacio y las citas coincidentes en Java (3)

Tengo una Cadena que necesito dividir en función del espacio y las comillas que coincidan exactamente.

Si el

string = "It is fun /"to write/" regular/"expression"

Después de la división quiero que el resultado sea:

Eso

es

divertido

"escribir"

regular

"expresión

La expresión regular de la que llegué a algo cercano a hacer esto fue:

STRING_SPLIT_REGEXP = "[^//s/"'']+|/"([^/"]*)/"|''([^'']*)''"

Gracias por adelantado por las respuestas.


Te encuentras con una limitación fundamental de expresiones regulares aquí. En general, no pueden detectar recursividad, profundidad, etc.

Entonces en tu cadena:

"It is fun /"to write/" regular/"expression"

Tanto el espacio entre ay write como el espacio entre /" y regular están todos dentro de las comillas. Regex no puede" contar "el número de citas de una manera flexible y tomar medidas basadas en él.

Necesitará escribir su propio analizador de cadenas para esto (o usar uno existente). Regex no puede manejarlo sin embargo.


El truco es usar una mirada flexible hacia adelante para afirmar que:

  • si hay un número par de citas en la entrada, debe haber un número par después del espacio, porque un número impar significa que el espacio está entre comillas
  • si hay un número impar de comillas en la entrada, debe haber un número impar después del espacio, porque un número par significa que el espacio está entre comillas

Lo tengo en una línea, pero es un whopper:

String[] parts = str.split("(//s+|(?<!//s)(?=/"))(?=(([^/"]*/"){2})*[^/"]*" + (str.matches("(([^/"]*/"){2})*[^/"]*") ? "" : "/"[^/"]*") + "$)");

Esto divide correctamente la cadena de ejemplo con o sin la cita final (ya sea que el término final incluya o no un espacio).


Parece que acabas de usar expresiones regulares de esta respuesta , pero como pudiste ver, no utiliza el método de split sino el de la clase Matcher . También esta respuesta se ocupa de '' donde su entrada no muestra signos de ello".

Para que pueda mejorar esta expresión regular eliminando el manejo de las partes '' que hará que se vea como

[^//s/"]+|/"([^/"]*)/"

Además, dado que desea incluir " como parte del token, no es necesario colocar la coincidencia entre " en un grupo separado, por lo tanto, deshágase de los paréntesis en /"([^/"]*)/" parte

[^//s/"]+|/"[^/"]*/"

Ahora todo lo que tiene que hacer es agregar un caso donde no habrá cierre " , pero en su lugar obtendrá el final de la cadena. Por lo tanto, cambie esta expresión Regex a

[^//s/"]+|/"[^/"]*(/"|$)

Después de esto, puedes usar Matcher, find todas las fichas de la tienda en algún lugar, digamos en la List .

Ejemplo:

String data = "It is fun /"to write/" regular/"expression"; List<String> matchList = new ArrayList<String>(); Pattern regex = Pattern.compile("[^//s/"]+|/"[^/"]*(/"|$)"); Matcher regexMatcher = regex.matcher(data); while (regexMatcher.find()) { System.out.println(regexMatcher.group()); matchList.add(regexMatcher.group()); }

Salida:

It is fun "to write" regular "expression

Expresión más compleja para manejar manejar esta información puede parecerse

String data = "It is fun /"to write/" regular /"expression"; for(String s : data.split("(?<!//G)(?<=//G[^/"]*(/"[^/"]{0,100000}/")?[^/"]*)((?<=/"(?!//s))|//s+|(?=/"))")) System.out.println(s);

pero este enfoque es muy complicado luego de escribir su propio analizador.

Tal analizador podría verse como

public static List<String> parse(String data) { List<String> tokens = new ArrayList<String>(); StringBuilder sb = new StringBuilder(); boolean insideQuote = false; char previous = ''/0''; for (char ch : data.toCharArray()) { if (ch == '' '' && !insideQuote) { if (sb.length() > 0 && previous != ''"'') addTokenAndResetBuilder(sb, tokens); } else if (ch == ''"'') { if (insideQuote) { sb.append(ch); addTokenAndResetBuilder(sb, tokens); } else { addTokenAndResetBuilder(sb, tokens); sb.append(ch); } insideQuote = !insideQuote; } else { sb.append(ch); } previous = ch; } addTokenAndResetBuilder(sb, tokens); return tokens; } private static void addTokenAndResetBuilder(StringBuilder sb, List<String> list) { if (sb.length() > 0) { list.add(sb.toString()); sb.delete(0, sb.length()); } }

Uso

String data = "It is fun /"to write/" regular/"expression/"xxx/"yyy"; for (String s : parse(data)) System.out.println(s);