Extraer pares de palabras usando String.split ()

Dado:

String input = "one two three four five six seven"; 

¿Hay una expresión regular que funcione con String.split() para tomar (hasta) dos palabras a la vez, de modo que:

 String[] pairs = input.split("some regex"); System.out.println(Arrays.toString(pairs)); 

resultados en esto:

 [one two, three four, five six, seven] 

Esta pregunta es sobre la división de expresiones regulares . No se trata de “encontrar una solución alternativa” u otras soluciones que “lo hagan funcionar de otra manera”.

Actualmente (incluido Java 8) es posible hacerlo con split() , pero en el mundo real no use este enfoque ya que parece estar basado en un error (look-behind en Java debería tener una longitud máxima obvia, pero esto la solución usa \w+ que no respeta esta limitación). En lugar de eso, use las clases Pattern y Matcher para evitar complicaciones excesivas y un infierno de mantenimiento, ya que este comportamiento puede cambiar en las próximas versiones de Java o en entornos similares a Java, como Android.


¿Es esto lo que estás buscando?
(puede reemplazar \\w con \\S para incluir todos los caracteres que no sean de espacio, pero para este ejemplo lo dejaré \\w ya que es más fácil leer expresiones regulares con \\w\\s luego \\S\\s )

 String input = "one two three four five six seven"; String[] pairs = input.split("(? 

salida:

 [one two, three four, five six, seven] 

\G es una coincidencia previa, (? es un lookbehind negativo.

En split estamos tratando de

  1. encontrar espacios -> \\s
  2. que no están pronosticados -> (?
  3. por alguna palabra -> \\w+
  4. con emparejado previamente (espacio) -> \\G
  5. antes que -> \\G\\w+ .

La única confusión que tuve al principio fue cómo funcionaría para el primer espacio, ya que queremos que ese espacio se ignore. La información importante es que \\G al inicio coincide con el inicio de String ^ .

Entonces, antes de la primera iteración, la expresión regular en el aspecto negativo detrás se verá como (? y dado que el primer espacio tiene ^\\w+ antes, no puede coincidir con la división. El espacio siguiente no tendrá este problema, por lo que se emparejará y la información al respecto (como su posición en input cadena de input ) se almacenará en \\G y se usará más adelante en el siguiente aspecto negativo detrás.

Por lo tanto, para 3er espacio, la expresión regular verificará si hay espacio coincidente previamente \\G y palabra \\w+ antes. Como el resultado de esta prueba será positivo, look-behind negativo no lo aceptará, por lo que este espacio no coincidirá, pero 4th Space no tendrá este problema porque el espacio antes no será el mismo que el almacenado en \\G (tendrá una posición diferente en input cadena de input ).


Además, si alguien desea separarse, digamos cada 3er espacio, puede usar este formulario (basado en la respuesta de @maybeWeCouldStealAVan , que se eliminó cuando publiqué este fragmento de respuesta).

 input.split("(?<=\\G\\w{1,100}\\s\\w{1,100}\\s\\w{1,100})\\s") 

En lugar de 100, puede usar un valor mayor que sea al menos el tamaño de la longitud de la palabra más larga en Cadena.


Me di cuenta de que también podemos usar + lugar de {1,maxWordLength} si queremos dividirnos con cada número impar como cada 3, 5 o 7, por ejemplo

 String data = "0,0,1,2,4,5,3,4,6,1,3,3,4,5,1,1"; String[] array = data.split("(?<=\\G\\d+,\\d+,\\d+,\\d+,\\d+),");//every 5th comma 

Esto funcionará, pero la longitud máxima de la palabra debe establecerse de antemano:

 String input = "one two three four five six seven eight nine ten eleven"; String[] pairs = input.split("(?<=\\G\\S{1,30}\\s\\S{1,30})\\s"); System.out.println(Arrays.toString(pairs)); 

Me gusta más la respuesta de Pshemo, es más corta y utilizable en longitudes de palabra arbitrarias, pero esto (como señaló @Pshemo) tiene la ventaja de ser adaptable a grupos de más de 2 palabras.

esto funcionó para mí (\w+\s*){2}\K\s ejemplo aquí

  • una palabra obligatoria seguida de un espacio opcional (\w+\s*)
  • repetido dos veces {2}
  • ignorar los caracteres previamente coincidentes \K
  • el espacio requerido

Puedes intentar esto:

 [az]+\s[az]+ 

Actualizado:

 ([az]+\s[az]+)|[az]+ 

enter image description here

Actualizado:

  String pattern = "([az]+\\s[az]+)|[az]+"; String input = "one two three four five six seven"; Pattern splitter = Pattern.compile(pattern); String[] results = splitter.split(input); for (String pair : results) { System.out.println("Output = \"" + pair + "\"");