2011-07-29 16 views
6

Iてるようなものの次のプロパティで文字列を分割するために正規表現を思い付くしようとして立ち往生:Javaの正規表現の分割文字列

  1. で区切り| (パイプ)個々の値はパイプが含まれている場合は、文字
  2. は、個々の値は、バックスラッシュで終わる場合、\(バックスラッシュ)
  3. でエスケープバックスラッシュでエスケープ

だから、たとえば、ここにいくつかの文字列があること私は別れたい:

  1. One|Two|Threeが得られるはず:["One", "Two", "Three"]
  2. One\|Two\|Threeが得られるはず:["One|Two|Three"]
  3. One\\|Two\|Three得なければならない:["One\", "Two|Three"]

今、私は、単一の正規表現でこれを分割可能性がどのように?

更新:あなたの多くが既に提案したように、これは正規表現の良いアプリケーションではありません。また、正規表現の解は、文字を反復するだけの場合よりも数桁も遅いです。

public static List<String> splitValues(String val) { 
    final List<String> list = new ArrayList<String>(); 
    boolean esc = false; 
    final StringBuilder sb = new StringBuilder(1024); 
    final CharacterIterator it = new StringCharacterIterator(val); 
    for(char c = it.first(); c != CharacterIterator.DONE; c = it.next()) { 
     if(esc) { 
      sb.append(c); 
      esc = false; 
     } else if(c == '\\') { 
      esc = true; 
     } else if(c == '|') { 
      list.add(sb.toString()); 
      sb.delete(0, sb.length()); 
     } else { 
      sb.append(c); 
     } 
    } 
    if(sb.length() > 0) { 
     list.add(sb.toString()); 
    } 
    return list; 
} 
+1

のは、それを明確にしましょう。あなたが望むのはこれです:分割|文字列から削除し、\で分割しないでください。文字列から\を削除し、最後に\\ |で分割します。 \を削除します。最初の部分からは\、2番目の部分から\。これは1つの正規表現でどうやって作ることができると思いますか?私にとって全く違った状況のようです... – user219882

+0

デリミタを変更することは可能ですか? – Paul

+0

私はあなたたちが正しいと思う!これは正規表現にとってはあまりにも多すぎるかもしれません。 –

答えて

13

トリックがsplit()メソッドを使用するのではない:私は文字の繰り返し処理を行うことになりました。そのため、エスケープ文字を検出するためにlookbehindを使用する必要がありますが、エスケープされた文字がエスケープされている場合(見つけた場合)は失敗します。あなたはトークンの代わりに区切り文字の一致させるために、代わりにfind()を使用する必要があります。

public static List<String> splitIt(String source) 
{ 
    Pattern p = Pattern.compile("(?:[^|\\\\]|\\\\.)+"); 
    Matcher m = p.matcher(source); 
    List<String> result = new ArrayList<String>(); 
    while (m.find()) 
    { 
    result.add(m.group().replaceAll("\\\\(.)", "$1")); 
    } 
    return result; 
} 

public static void main(String[] args) throws Exception 
{ 
    String[] test = { "One|Two|Three", 
        "One\\|Two\\|Three", 
        "One\\\\|Two\\|Three", 
        "One\\\\\\|Two" }; 
    for (String s :test) 
    { 
    System.out.printf("%n%s%n%s%n", s, splitIt(s)); 
    } 
} 

出力:

One|Two|Three 
[One, Two, Three] 

One\|Two\|Three 
[One|Two|Three] 

One\\|Two\|Three 
[One\, Two|Three] 

One\\\|Two 
[One\|Two] 
+0

それは印象的です。パターンの仕組みを説明できますか?私はまだ正規表現に苦しんでいます。 – Paul

+0

WOW !!これは甘いです!私は正規表現がトリックを行うことができることを知っていた:-) –

+0

これは魅力のように動作します!再びありがとう@アランムーア!今、どうやってその逆をしますか? –

関連する問題