web-dev-qa-db-ja.com

string.split( "\\ S")の仕組み

Ganesh and Sharmaの本Oracle_certified_professional_Java_se_7_programmer_exams_1z0-804_and_1z0-805から質問をしていました。

1つの質問は次のとおりです。

  1. 次のプログラムを検討し、出力を予測します。

      class Test {
    
        public static void main(String args[]) {
          String test = "I am preparing for OCPJP";
          String[] tokens = test.split("\\S");
          System.out.println(tokens.length);
        }
      }
    

    a)0

    b)5

    c)12

    d)16

\ Sは正規表現であり、スペース以外の文字を区切り文字として扱うことを理解しています。しかし、正規表現がどのようにマッチングを行うのか、分割によって生成される実際のトークンは何なのか、私は困惑していました。

次のようにトークンを印刷するコードを追加しました

for (String str: tokens){
  System.out.println("<" + str + ">");
}

そして、私は次の出力を得ました

16

<>

< >

<>

< >

<>

<>

<>

<>

<>

<>

<>

<>

< >

<>

<>

< >

たくさんの空の文字列トークン。私はこれを理解していません。

上記のテキストで区切り文字がスペース以外の文字である場合、すべてのアルファベット文字が区切り文字として機能するので、空の文字列をもたらすトークンと一致する場合は21個のトークンがあるはずだと線に沿って考えていました。 Javaの正規表現エンジンがこれをどのように機能させているのか、私にはわかりません。私のためにこのコードに光を当てることができる正規表現の指導者はいますか?

13
Frank Brosnan

最初は\s(小文字)で始まります。これは空白の正規表現文字クラス、つまりスペース ''タブ '\ t'、改行文字 '\ n'および '\ r'、垂直ですタブ「\ v」と他の文字の束。

\S(大文字)はこれの反対であるため、空白文字以外の文字を意味します。

したがって、I am preparing for OCPJPを使用してこの文字列「\S」を分割すると、文字ごとに文字列を効果的に分割できます。トークン配列の長さが16である理由。

今、これらが空である理由について。

次の文字列を考慮してください:Hello,World,を使用して分割すると、次の内容を持つ長さ2の文字列配列になります:HelloおよびWorld,はいずれの文字列にも含まれておらず、消去されていることに注意してください。

同じことがI am preparing for OCPJP文字列でも発生し、分割されており、正規表現に一致するポイントは戻り値のいずれにもありません。また、その文字列のほとんどの文字の後に別の文字が続くため、長さがゼロの文字列が大量に読み込まれ、空白文字のみが保持されます。

5
PeterK

APIからコピー ドキュメント :(太字は私のものです)

public String[] split(String regex)

この文字列を、指定された正規表現の一致で分割します。このメソッドは、指定された式とゼロの制限引数を使用して2引数のsplitメソッドを呼び出すかのように機能します。 したがって、末尾の空の文字列は結果の配列に含まれません。

たとえば、文字列「boo:and:foo」は、これらの式で次の結果をもたらします。

 Regex  Result
   :    { "boo", "and", "foo" }
   o    { "b", "", ":and:f" }

最後の2つの「o」が削除された2番目の例を確認します。質問に対する答えは"OCPJP"部分文字列は、空ではない文字列の後に続かないセパレータのコレクションとして扱われるため、その部分はトリミングされます。

12
Pablo Lozano

結果が21ではなく16である理由は、 Splitのjavadoc からです。

したがって、末尾の空の文字列は結果の配列に含まれません。

これは、たとえば、あなたが言うなら

"/abc//def/ghi///".split("/")

結果には5つの要素が含まれます。最初は""になります。これは末尾の空の文字列ではないためです。その他は"abc""""def"、および"ghi"になります。ただし、残りの空の文字列は配列から削除されます。

投稿された場​​合:

"I am preparing for OCPJP".split("\\S")

それは同じことです。スペース以外の文字は区切り文字であるため、各文字は区切り文字ですbutOCPJP文字は基本的にカウントされませんその後破棄されます。したがって、"I am preparing for"には15文字あるため、16個の部分文字列の区切りとして扱われます(最初は""、最後は" ")。

6
ajb