7

私はscalaが初めてです。二重引用符で区切られた文字列を照合しようとしていますが、次の動作に少し戸惑っています。

私が次のことをした場合:

val stringRegex = """"([^"]*)"(.*$)"""
val regex = stringRegex.r
val tidyTokens = Array[String]("1", "\"test\"", "'c'", "-23.3")
tidyTokens.foreach {
    token => if (token.matches (stringRegex)) println (token + " matches!")
}

私は得る

"test" matches!

それ以外の場合は、次のようにします。

tidyTokens.foreach {
    token => token match {
        case regex(token) => println (token + " matches!")
        case _ => println ("No match for token " + token)
    }
}

私は得る

No match for token 1
No match for token "test"
No match for token 'c'
No match for token -23.3

2番目のケースで「テスト」が一致しないのはなぜですか?

4

1 に答える 1

9

正規表現を使用します。

 "([^"]*)"(.*$)

でコンパイルすると.r、この文字列はregexオブジェクトを生成します。これは、入力文字列と一致する場合、キャプチャされた2([^"]*)つの文字列 (1 つは 用、もう1 つは 用) を生成する必要があり(.*$)ます。あなたのコード

  case regex(token) => ...

これを反映する必要があるので、多分あなたはしたいです

  case regex(token, otherStuff) => ...

あるいは単に

  case regex(token, _) => ...

なんで?メソッドを持つオブジェクトであるため、case regex(matchedCaputures...)構文が機能するためです。 (おおまかに)次のように変換されます。regexunapplySeqcase regex(token) => ...

 case List(token) => ...

List(token)戻り値はどこにありますかregex.unapplySeq( inputString ):

 regex.unapplySeq("\"test\"") // Returns Some(List("test", ""))

正規表現は文字列と一致します"test"が、caseステートメントでは、正規表現エクストラクターのunapplySeqメソッドは2つの文字列のリストを返します。これは、正規表現がキャプチャすると言っているためです。残念ながら、正規表現は実行時に文字列からコンパイルされるため、コンパイラはここでは役に立ちません。

1 つの代替方法は、非キャプチャ グループを使用することです。

 val stringRegex = """"([^"]*)"(?:.*$)"""
 //                             ^^

次に、メソッドが単一のキャプチャされたグループのみを返すregex抽出オブジェクトになる ため、コードが機能します。unapplySeq

 tidyTokens foreach { 
    case regex(token) => println (token + " matches!")
    case t => println ("No match for token " + t)
 }

//の仕組みをよりよく理解するには、 Extractor Objectsのチュートリアルをご覧ください。applyunapplyunapplySeq

于 2013-02-27T18:26:04.113 に答える