15

私は、ガネーシュとシャルマによる本 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

    イ) 5

    ウ 12

    エ) 16

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

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

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

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

16

<>

< >

<>

< >

<>

<>

<>

<>

<>

<>

<>

<>

< >

<>

<>

< >

そのため、空の文字列トークンがたくさんあります。私はこれを理解していません。

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

4

3 に答える 3

12

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

public String[] split(String regex)

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

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

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

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

于 2014-10-09T14:43:41.010 に答える
8

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

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

これは、たとえば次のように言うと、

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

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

投稿された場​​合:

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

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

于 2014-10-09T14:46:55.640 に答える
7

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

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

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

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

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

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

于 2014-10-09T14:33:33.507 に答える