2009-07-04 17 views
12

Czy istnieje alternatywa dla Javy w wersji shlex? Chciałbym móc rozdzielać znaki rozdzielane cudzysłowami, tak jak robota je przetwarza. Na przykład, jeśli chciałbym wysłać: shlex alternative dla Java

one two "three four"
i przeprowadzić split, chciałbym otrzymać tokeny
one
two
three four

+0

Znacząco - "jak skorupa ich przetwarza" jest dość trudnym zadaniem; 'shlex' robi to dobrze, ale wiele naiwnych algorytmów tego nie robi. Na przykład w powłoce, "" trzy cztery "i" trzy "" cztery "są dokładnie równoważne, podobnie jak" trzy \ cztery ". –

Odpowiedz

6

Spójrz na Apache Commons Lang:

org.apache.commons.lang.text. StrTokenizer powinien być w stanie robić to, co chcesz:

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

Niestety, w przeciwieństwie do 'shlex', commons.lang nie jest kompatybilny z POSIX. '(-> (StrTokenizer." \ "Foo \" 'bar'baz ") (.getTokenList))' zwraca pojedynczy wpis zawierający '" foo "' bar'baz', w przeciwieństwie do (poprawnego)' foobarbaz' . –

+0

@CharlesDuffy czy znasz prawdziwą odpowiedź? – bukzor

+0

@bukzor, który zakłada, że ​​* jest * jeden. Zgodnie z moją wiedzą, takie narzędzie nie zostało napisane w tym czasie, jeśli nie wykorzystano shitu Pythona z Javy przez Jython (możliwe, ale raczej dużego łańcucha zależności). –

7

miałem dziś podobny problem, a nie wyglądać wszelkich standardowych opcji takich jak StringTokenizer, StrTokenizer, SC dobrze pasowali. Jednak nie jest trudno wdrożyć podstawy.

Ten przykład obsługuje wszystkie przypadki brzegowe, które są obecnie komentowane w innych odpowiedziach. Ostrzegam, nie sprawdziłem jeszcze pełnej zgodności z POSIX. Treść obejmująca testy jednostkowe dostępne on GitHub - wydane w domenie publicznej za pośrednictwem nielicencjonowania.

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

Czy rozważasz dołączenie do tego licencji (lub wyraźne przekazanie jej do domeny publicznej)? –

+0

Ach, jest, ostatnia linia tej strony: wkład użytkownika na licencji cc by-sa 3.0 z wymaganiem atrybucji – bukzor

+0

@RayMyers: Nadal musimy wiedzieć, czy to jest twoja własna praca, w przeciwnym razie licencja jest nieznana. Również licencja CC-BY-SA nie jest w pełni zgodna z licencją Apache firmy Hadoop ([musiałbym używać jej niezmodyfikowaną] (http://www.apache.org/legal/resolved.html#cc-sa)) . Jeśli dedykujesz ten kod w [Unlicense] (http://unlicense.org/), te problemy znikną, inaczej będę musiał napisać coś podobnego od zera. ... Życzę, aby SO zmieniło swoją domyślną licencję. – bukzor