2012-03-18 30 views
3

私は正規表現を学んでいて、私はグリップを始めていたと思っていました。しかし、その後... 正規表現 w w *を使用して文字列を分割しますか? w +?

私は、文字列を分割しようとしたとして、私はそのような単純なことを理解するのに役立つ必要があります。

String input = "abcde"; 
System.out.println("[a-z] " + Arrays.toString(input.split("[a-z]"))); 
System.out.println("\\w " + Arrays.toString(input.split("\\w"))); 
System.out.println("\\w*? " + Arrays.toString(input.split("\\w*?"))); 
System.out.println("\\w+? " + Arrays.toString(input.split("\\w+?"))); 

The output is 
[a-z] - [] 
\w - [] 
\w*? - [, a, b, c, d, e] 
\w+? - [] 

はなぜ2つの最初の行のいずれかが任意の文字で文字列を分割しません。 ? 3番目の式\ w *?(疑問符が貪欲を防ぐ)は、期待どおりに動作し、文字列ごとに文字列を分割します。星の0個以上の一致は、空の配列を返します。

は私がメモ帳内++プログラム内での発現を試みたし、それがでて5試合を示しています。あなたは正規表現で文字列を分割した場合、基本的に、これは本当に私

+0

あなたがJavaで正規表現の宿題を割り当てられているとは思えません。\\ dd \\ oo \\ uu \\ bb \\ ll \\ ee \\ \\ bb \\ aa \\ cc \\ kk \\ ss \\ ll \\ aa \\ ss \\ hh \\ ee \\ ss !!どのような拷問!さらに、正規表現の構文やデバッグなどのコンパイル時のチェックもしていません。Javaはこの種の作業にはあまり便利ではありません。 regexの作業をより同情的な言語で開発し、最終結果をJavaに転送する必要があります。 – tchrist

+0

@tchristあなたはどのような言語について考えていますか? – Kennet

+0

sedやawkのようなシェルツールに加えて、PerlとRubyは第一級の正規表現を持っています。そしてPythonでさえ二重バックスラッシュをスキップできます。 Perlは正規表現デバッガを持つ唯一のものです。 – tchrist

答えて

8

パズル

Scanner ls = new Scanner(input); 
while(ls.hasNext()) 
    System.out.format("%s ", ls.findInLine("\\w"); 

Output is: a b c d e 

あなたを文字列をどこで切り取るべきかを教えてください。これは必然的にあなたが正規表現と一致するものを切り捨てます。つまり、\wに分割すると、すべての文字が分割点になり、それらの間の部分文字列(すべて空)が返されます。 the documentationで説明されているように、Javaは後続の空の文字列を自動的に削除します。

これはまた、文字が間違っている(前後)すべての位置に一致するため、怠惰な一致\w*?がすべての文字を与える理由についても説明します。残っているのは、文字列自体の文字です。

のは、それを打破してみましょう:

  1. [a-z]\wは、あなたの文字列が

    abcde 
    

    そしてMATC \w+?

    ある次のようにHESは、以下のとおりです。

    a b c d e 
    └─┘└─┘└─┘└─┘└─┘ 
    

    空ですすべてが試合、間のサブストリングであなたを残しています。

    上記の3つの正規表現は、すべてが単一の文字にのみ一致するため、同じ点で動作します。 \w+?は、他の制約がないため、+?がまったく似ていない(それは結局怠け者です)よりもマッチングを試みるので、そうするでしょう。

  2. \w*?

    a b c d e 
    └┘ └┘ └┘ └┘ └┘ └┘ 
    

    この場合、マッチは、次のサブストリングであなたを残して、間の文字です:

    "", "a", "b", "c", "d", "e", "" 
    

    Javaはいえ、離れ末尾の空の1を投げます。

+1

Javaの 'split'はPerlの' split'を模倣しているので、末尾のnullフィールドを捨てます。どちらの言語でも、 '-1'の' split'に別の引数を追加することでその動作を抑制できます。 – tchrist

1

String.splitパターンの各マッチで文字列を切断:このメソッドによって返さ

アレイは、与えられた表現と一致するか、終了し、別のサブストリングで終了し、この文字列の各部分が含まれていストリングの終わりまでに。

[a-z]のようなパターンが一致するたびに、その一致で文字列が切り取られます。文字列のすべての文字がパターンと一致するので、結果の配列は空です(空の文字列は削除されます)。

\w\w+?(1つ以上の\w)が同じですが、できるだけ繰り返しは少ないです。可能であれば0の繰り返しと一致するように*?の量指定子があるため、\w*?の結果は期待通りです。空の文字列です。そして、指定された文字列の各位置に空文字列があります。

+0

これはまた役に立ちました、ありがとう! – Kennet

2

これらのコールをそれぞれString#split(String)に分割しましょう。 Javaのドキュメントから、 "メソッドは、指定された式と制限引数が0であるthe two-argument split methodを呼び出すかのように機能します。したがって、空の文字列は結果の配列に含まれません。"

"abcde".split("[a-z]"); // => [] 

これは、すべての文字(a、b、c、d、e)に一致し、その間の空の文字列のみに一致します。

"abcde".split("\\w")); // => [] 

ここでも、文字列内のすべての文字は、単語文字(\w)なので、結果は省略されている空の文字列です。この場合

"abcde".split("\\w*?")); // => ["", "a", "b", "c", "d", "e"] 

*は(一旦各文字の間に一度文字列の先頭に)空の発現を7回一致(\w)「前号のゼロまたはそれ以上」を意味します。だから、最初の空の文字列と各文字を取得します。

ここ
"abcde".split("\\w+?")); // => [] 

+手段省略されている唯一の空の文字列、その結果、全体の入力文字列と一致する(\w)「前項目の1つまたは複数の」。

input.split(regex, -1)でこれらの例をもう一度お試しください。すべての空文字列が表示されます。

+0

私もあなたの助けをお寄せいただきありがとうございます。 – Kennet

+0

@Kennet:確かに、あなたが有益だと思う答えをupvotingしてください。 – maerics

関連する問題