2009-07-04 9 views
12

Gibt es eine shlex Alternative für Java? Ich möchte in der Lage sein, durch Trennzeichen getrennte Strings zu teilen, so wie die Shell sie verarbeiten würde. Zum Beispiel, wenn ich senden würde: shlex Alternative für Java

one two "three four"
und eine Spaltung durchführen, würde Ich mag die Zeichen bei Apache Commons Lang
one
two
three four

+0

Bemerkenswert - "wie die Shell sie verarbeiten würde" ist eine ziemlich schwierige Aufgabe; 'shlex' macht es gut, aber viele naive Algorithmen nicht. Zum Beispiel sind in der Shell "drei vier" und "drei" vier genau gleichwertig wie "drei \ vier". –

Antwort

6

Blick erhalten:

org.apache.commons.lang.text. StrTokenizer sollte in der Lage sein zu tun, was Sie wollen:

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

Leider ist commons.lang im Gegensatz zu 'shlex' nicht POSIX-kompatibel. '(-> (StrTokenizer." Foo \ "'bar'baz") (.getTokenList)) 'gibt einen einzelnen Eintrag zurück, der' 'foo' 'bar'baz' enthält, im Gegensatz zum (korrekten)' foobarbaz' . –

+0

@CharlesDuffy kennst du die wahre Antwort? – bukzor

+0

10 @bukzor, das vermutet, dass es * eins gibt. Soweit ich weiß, wurde ein solches Tool zu diesem Zeitpunkt noch nicht geschrieben, abgesehen von der Verwendung von Pythons Shlex aus Java über Jython (möglich, aber eher eine große Abhängigkeitskette). –

7

ich heute hatte ein ähnliches Problem, und es sah nicht wie alle Standardoptionen wie StringTokenizer, StrTokenizer, Sc Anner passte gut. Es ist jedoch nicht schwer, die Grundlagen zu implementieren.

In diesem Beispiel werden alle Randfälle behandelt, die derzeit zu anderen Antworten kommentiert werden. Seien Sie gewarnt, ich habe es noch nicht auf volle POSIX-Kompatibilität überprüft. Gist einschließlich Komponententests verfügbar on GitHub - veröffentlicht in der Öffentlichkeit über die Unlizenz.

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

Würden Sie daran denken, eine Lizenz hinzuzufügen (oder explizit an die Public Domain zu spenden)? –

+0

Ah, da ist es, letzte Zeile dieser Seite: Benutzerbeiträge unter cc lizenziert by-sa 3.0 mit Attribution erforderlich – bukzor

+0

@RayMyers: Wir müssen noch wissen, ob das deine eigene Arbeit ist, ansonsten ist die Lizenz unbekannt. Außerdem ist die CC-BY-SA-Lizenz nicht vollständig kompatibel mit der Apache-Lizenz von Hadoop ([ich müsste sie unverändert verwenden]) (http://www.apache.org/legal/resolved.html#cc-sa)) . Wenn Sie diesen Code unter [die Unlicense] (http://unlicense.org/) widmen, gehen diese Probleme weg, ansonsten muss ich von Grund auf neu schreiben. ... Ich wünschte, SO würde ihre Standardlizenz ändern. – bukzor