2009-07-04 19 views
12

¿Hay un shlex alternativa para Java? Me gustaría poder dividir cadenas delimitadas por comillas, como el shell las procesaría. Por ejemplo, si yo mando: shlex alternative for Java

one two "three four"
y realizo una división, me gustaría recibir las fichas
one
two
three four

+0

Cabe destacar que "como el caparazón los procesaría" es una tarea bastante difícil; 'shlex' lo hace bien, pero muchos algoritmos ingenuos no lo harán. Por ejemplo, en shell, '" tres cuatro "' y '" tres "'' cuatro 'son exactamente equivalentes, como lo es' three \ four'. –

Respuesta

6

Mira Apache Commons Lang:

org.apache.commons.lang.text. StrTokenizer debe ser capaz de hacer lo que quiera:

 
new StringTokenizer("one two \"three four\"", ' ', '"').getTokenArray(); 
+2

Desafortunadamente, a diferencia de 'shlex', commons.lang no es compatible con POSIX. '(-> (StrTokenizer." \ "Foo \" 'bar'baz ") (.getTokenList))' devuelve una sola entrada que contiene '" foo "' bar'baz', en oposición a la (correcta)' foobarbaz' . –

+0

@CharlesDuffy ¿conoces la verdadera respuesta? – bukzor

+0

@bukzor, que supone que * is * one. Que yo sepa, tal herramienta no se ha escrito en este momento, excepto usar el shlex de Python desde Java a través de Jython (posible, pero más bien una gran cadena de dependencia para atraer). –

7

que tenía un problema similar en la actualidad, y no se parece a ninguna opciones estándar tales como StringTokenizer, StrTokenizer, Sc anner fueron una buena opción. Sin embargo, no es difícil implementar lo básico.

Este ejemplo maneja todos los casos extremos actualmente comentados en otras respuestas. Tenga cuidado, todavía no lo he comprobado para ver si cumple con POSIX. Gist incluyendo pruebas unitarias disponibles on GitHub - lanzado en dominio público a través de la licencia no autorizada.

public List<String> parseArgs(CharSequence argString) { 
    List<String> tokens = new ArrayList<String>(); 
    boolean escaping = false; 
    char quoteChar = ' '; 
    boolean quoting = false; 
    StringBuilder current = new StringBuilder() ; 
    for (int i = 0; i<argString.length(); i++) { 
     char c = argString.charAt(i); 
     if (escaping) { 
      current.append(c); 
      escaping = false; 
     } else if (c == '\\' && !(quoting && quoteChar == '\'')) { 
      escaping = true; 
     } else if (quoting && c == quoteChar) { 
      quoting = false; 
     } else if (!quoting && (c == '\'' || c == '"')) { 
      quoting = true; 
      quoteChar = c; 
     } else if (!quoting && Character.isWhitespace(c)) { 
      if (current.length() > 0) { 
       tokens.add(current.toString()); 
       current = new StringBuilder(); 
      } 
     } else { 
      current.append(c); 
     } 
    } 
    if (current.length() > 0) { 
     tokens.add(current.toString()); 
    } 
    return tokens; 
} 
+0

¿Consideraría adjuntar una licencia a esto (o donarlo explícitamente al dominio público)? –

+0

Ah, ahí está, última línea de esta página: contribuciones de los usuarios con licencia bajo cc by-sa 3.0 con atribución requerida – bukzor

+0

@RayMyers: Todavía necesitamos saber si este es su propio trabajo, de lo contrario la licencia es desconocida. Además, la licencia CC-BY-SA no es completamente compatible con la licencia Apache de Hadoop ([Necesitaría usarla sin modificar] (http://www.apache.org/legal/resolved.html#cc-sa)) . Si dedicas este código a [Unlicense] (http://unlicense.org/) estos problemas desaparecen, de lo contrario tendré que escribir similares desde cero. ... Deseo que SO cambie su licencia predeterminada. – bukzor