2009-07-04 7 views
12

shlex Javaの代替ですか?私はシェルがそれらを処理するように引用符で区切られた文字列を分割できるようにしたいと思います。例えば、私が送信したい場合:shlexの代替Java版

one two "three four"
と分割を行い、私は
one
two
three four

+0

特に、「シェルが処理するように」はかなり難しい作業です。 'shlex'はそれをうまく行いますが、多くの素朴なアルゴリズムはそうしません。たとえば、シェルでは、 '' three four "と' 'three" "four"はまったく同じで、 'three \ four'も同様です。 –

答えて

6

ルックApache Commons Langでトークンを受け取りたい:

org.apache.commons.lang.textを。 StrTokenizerは、あなたがやりたいことができるはずです。

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

残念ながら、 'shlex'とは異なり、commons.langはPOSIX互換ではありません。 '' '' - ''(StrTokenizer。\ "foo \" bar'baz ")(.getTokenList))'( '' foobarbaz''とは対照的に) '' foo''bar'baz'を含む単一のエントリを返します。 。 –

+0

@CharlesDuffyあなたは本当の答えを知っていますか? – bukzor

+0

@bukzorは、*が* 1であると推定します。私の知る限り、PythonのshlexをJavaからJython経由で使用するのは現時点では手がかりではありません(可能性はありますが、むしろ大きな依存関係のチェーンが必要です)。 –

7

私は今日、同様の問題があったが、それは、そのようなStringTokenizerは、StrTokenizer、SCとの任意の標準的なオプションのようには見えませんでしたannerは良いフィット感でした。しかし、基本を実装するのは難しいことではありません。

この例では、現在他の回答にコメントされているすべてのエッジケースを処理します。注意してください、私は完全なPOSIX準拠のためにそれをチェックしていません。利用可能な単体テストを含む要点on GitHub - ライセンス解除によりパブリックドメインでリリースされました。

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

これにライセンスを付与する(またはパブリックドメインに明示的に寄付する)ことを検討しますか? –

+0

ああ、このページの最後の行です:寄付を必要とするcc by-sa 3.0のライセンスが必要です – bukzor

+0

@RayMyers:これはあなた自身の仕事であるかどうかを知る必要があります。また、CC-BY-SAライセンスはHadoopのApacheライセンスと完全には互換性がありません([私はそのまま使用する必要があります](http://www.apache.org/legal/resolved.html#cc-sa))。 。 [The Unlicense](http://unlicense.org/)でこのコードを捧げると、これらの問題はなくなります。そうでなければ、私は同じように書く必要があります。 ...私はSOがデフォルトライセンスを変更することを望みます。 – bukzor