type=class
superclass=Object
included=
extended=
dynamically_included=
dynamically_extended=
library=strscan
aliases=
aliasof=

StringScanner は文字列スキャナクラスです。
簡単に高速なスキャナを記述できます。

    s = StringScanner.new('This is an example string')
    s.eos?            #=> false

    p s.scan(/\w+/)   #=> "This"
    p s.scan(/\w+/)   #=> nil
    p s.scan(/\s+/)   #=> " "
    p s.scan(/\s+/)   #=> nil
    p s.scan(/\w+/)   #=> "is"
    s.eos?            #=> false

    p s.scan(/\s+/)   #=> " "
    p s.scan(/\w+/)   #=> "an"
    p s.scan(/\s+/)   #=> " "
    p s.scan(/\w+/)   #=> "example"
    p s.scan(/\s+/)   #=> " "
    p s.scan(/\w+/)   #=> "string"
    s.eos?            #=> true

    p s.scan(/\s+/)   #=> nil
    p s.scan(/\w+/)   #=> nil

StringScanner オブジェクトはスキャンする文字列と「スキャンポインタ」のセットです。
スキャンポインタとはスキャンしおわったところを示すインデックスのことです。
オブジェクト作成直後にはスキャンポインタは文字列先頭にあり、
その地点でのみマッチを試します。マッチしたらその後ろにポインタを進めます。

    ## a string and a scan pointer   ("_" = scan pointer)

    s = StringScanner.new('This is an example string')
    _This is an example string     s.eos? = false
    s.scan(/\w+/)
    This_ is an example string     s.eos? = false
    s.scan(/\s+/)
    This _is an example string     s.eos? = false
    s.scan(/\w+/)
    This is_ an example string     s.eos? = false
    s.scan(/\s+/)
    This is _an example string     s.eos? = false
    s.scan(/\w+/)
    This is an_ example string     s.eos? = false
    s.scan(/\s+/)
    This is an _example string     s.eos? = false
    s.scan(/\w+/)
    This is an example_ string     s.eos? = false
    s.scan(/\s+/)
    This is an example _string     s.eos? = false
    s.scan(/\w+/)
    This is an example string_     s.eos? = true


現在のスキャンポインタがさす地点以外でもマッチしたい場合は、[[m:StringScanner#scan_until]]など
を使ってください。

例: scan, scan_until の動作の違い

  def case1
    s = StringScanner.new('test string')
    p s.scan(/t/)       #=> "t"
    p s.scan(/\w+/)     #=> "est"
    p s.scan(/string/)  #=> nil
    p s.scan(/\s+/)     #=> " "
    p s.scan(/string/)  #=> "string"
  end
  
  def case2
    s = StringScanner.new('test string')
    p s.scan_until(/t/)       #=> "t"
    p s.scan_until(/\w+/)     #=> "est"
    p s.scan_until(/string/)  #=> " string"
    p s.scan_until(/\s+/)     #=> nil
    p s.scan_until(/string/)  #=> nil
  end
  
  p "case1"
  case1
  p "case2"
  case2

スキャンポインタの位置は文字単位でなくバイト単位となります。

      # vim:set fileencoding=euc-jp:
      require 'strscan'
      s = StringScanner.new("るびい") # 文字コードはEUC-JPとします
      p s.exist?(/び/) #=> 4

StringScanner は $~ $& $1 $2 …… などの正規表現関連変数を
セットしません。代わりに [[m:StringScanner#[] ]], [[m:StringScanner#matched?]] などの
マッチデータ関連メソッドを使ってください。
