StringScanner は文字列スキャナクラスです。簡単に高速なスキャナを記述できます。
require 'strscan' 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 オブジェクトはスキャンする文字列と「スキャンポインタ」のセットです。スキャンポインタとはスキャンしおわったところを示すインデックスのことです。オブジェクト作成直後にはスキャンポインタは文字列先頭にあり、その地点でのみマッチを試します。マッチしたらその後ろにポインタを進めます。
require 'strscan' ## 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
現在のスキャンポインタがさす地点以外でもマッチしたい場合は、StringScanner#scan_untilなどを使ってください。
例: scan, scan_until の動作の違い
require 'strscan' 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 …… などの正規表現関連変数をセットしません。代わりに StringScanner#[], StringScanner#matched? などのマッチデータ関連メソッドを使ってください。
must_C_version -> self
[permalink][rdoc]このメソッドは後方互換性のために定義されています。
new(str, dup = false) -> StringScanner
[permalink][rdoc]新しい StringScanner オブジェクトを生成します。
使用例
require 'strscan' 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+/) #=> " "
self << str -> self
[permalink][rdoc]concat(str) -> self
操作対象の文字列に対し str を破壊的に連結します。マッチ記録は変更されません。
selfを返します。
使用例
require 'strscan' s = StringScanner.new('test') # => #<StringScanner 0/4 @ "test"> s.match(/\w(\w*)/) # => "test" s[0] # => "test" s[1] # => "est" s << ' string' # => #<StringScanner 4/11 "test" @ " stri..."> s[0] # => "test" s[1] # => "est" s.match(/\s+/) # => " " s.match(/\w+/) # => "string"
この操作は StringScanner.new に渡した文字列にも影響することがあります。
require 'strscan' str = 'test' s = StringScanner.new(str) # => #<StringScanner 0/4 @ "test"> s << ' string' # => #<StringScanner 0/11 @ "test ..."> str # => "test string"
self[nth] -> String | nil
[permalink][rdoc]前回マッチした正規表現の nth 番目のかっこに対応する部分文字列を返します。インデックス 0 はマッチした部分全体です。前回のマッチが失敗していると常に nil を返します。
require 'strscan' s = StringScanner.new('test string') s.scan(/\w(\w)(\w*)/) # => "test" s[0] # => "test" s[1] # => "e" s[2] # => "st" s.scan(/\w+/) # => nil s[0] # => nil s[1] # => nil s[2] # => nil s.scan(/\s+/) # => " " s[0] # => " " s[1] # => nil s[2] # => nil s.scan(/\w(\w)(\w*)/) # => "string" s[0] # => "string" s[1] # => "t" s[2] # => "ring"
beginning_of_line? -> bool
[permalink][rdoc]bol? -> bool
スキャンポインタが行頭を指しているなら true を、行頭以外を指しているなら false を返します。
行頭の定義は、文字列先頭かまたは \n の直後を指していることです。文字列末尾は必ずしも行頭ではありません。
使用例
require 'strscan' s = StringScanner.new("test\nstring") s.bol? # => true s.scan(/\w+/) s.bol? # => false s.scan(/\n/) s.bol? # => true s.scan(/\w+/) s.bol? # => false
charpos -> Integer
[permalink][rdoc]現在のスキャンポインタのインデックスを文字単位で返します。
使用例
require 'strscan' s = StringScanner.new("abcädeföghi") s.charpos # => 0 s.scan_until(/ä/) # => "abcä" s.pos # => 5 s.charpos # => 4
[SEE_ALSO] StringScanner#pos
check(regexp) -> String | nil
[permalink][rdoc]現在位置から regexp とのマッチを試みます。マッチに成功したらマッチした部分文字列を返します。マッチに失敗したら nil を返します。
このメソッドはマッチが成功してもスキャンポインタを進めません。
使用例
require 'strscan' s = StringScanner.new('test string') s.check(/\w+/) # => "test" s.pos # => 0 s.matched # => "test" s.check(/\s+/) # => nil s.matched # => nil
check_until(regexp) -> String | nil
[permalink][rdoc]regexp が一致するまで文字列をスキャンします。マッチに成功したらスキャン開始位置からマッチ部分の末尾までの部分文字列を返します。マッチに失敗したら nil を返します。
このメソッドはマッチが成功してもスキャンポインタを進めません。
使用例
require 'strscan' s = StringScanner.new('test string') s.check_until(/str/) # => "test str" s.matched # => "str" s.pos # => 0 s.pre_match # => "test "
terminate -> self
[permalink][rdoc]clear -> self
スキャンポインタを文字列末尾後まで進め、マッチ記録を捨てます。
pos = self.string.size と同じ動作です。
require 'strscan' s = StringScanner.new('test string') s.scan(/\w+/) # => "test" s.matched # => "test" s.pos # => 4 s[0] # => "test" s.terminate s.matched # => nil s[0] # => nil s.pos # => 11
StringScanner#clear は将来のバージョンで削除される予定です。代わりに StringScanner#terminate を使ってください。
eos? -> bool
[permalink][rdoc]empty? -> bool
スキャンポインタが文字列の末尾を指しているなら true を、末尾以外を指しているなら false を返します。
使用例
require 'strscan' s = StringScanner.new('test string') s.eos? # => false s.scan(/\w+/) s.scan(/\s+/) s.scan(/\w+/) s.eos? # => true
StringScanner#empty? は将来のバージョンで削除される予定です。代わりに StringScanner#eos? を使ってください。
exist?(regexp) -> Integer | nil
[permalink][rdoc]スキャンポインタの位置から,次にマッチする文字列の末尾までの長さを返します。
マッチに失敗したら nil を返します。
このメソッドはマッチが成功してもスキャンポインタを進めません。
使用例
require 'strscan' s = StringScanner.new('test string') s.exist?(/s/) # => 3 s.exist?(//) # => 0 s.scan(/\w+/) # => "test" s.exist?(/s/) # => 2 s.exist?(/e/) # => nil
get_byte -> String | nil
[permalink][rdoc]getbyte -> String | nil
1 バイトスキャンして文字列で返します。スキャンポインタをその後ろに進めます。スキャンポインタが文字列の末尾を指すなら nil を返します。
StringScanner#getbyte は将来のバージョンで削除される予定です。代わりに StringScanner#get_byte を使ってください。
使用例
require 'strscan' utf8 = "\u{308B 3073 3044}" s = StringScanner.new(utf8.encode("EUC-JP")) p s.get_byte #=> "\xA4" p s.get_byte #=> "\xEB" p s.get_byte #=> "\xA4" p s.get_byte #=> "\xD3" p s.get_byte #=> "\xA4" p s.get_byte #=> "\xA4" p s.get_byte #=> nil
getch -> String | nil
[permalink][rdoc]一文字スキャンして文字列で返します。スキャンポインタをその後ろに進めます。スキャンポインタが文字列の末尾を指すならnilを返します。
一文字の定義は、与えた文字列のエンコードに依存します。
使用例
require 'strscan' utf8 = "\u{308B 3073 3044}" s = StringScanner.new(utf8.encode("UTF-8")) p s.getch # => "る" p s.getch # => "び" p s.getch # => "い" p s.getch # => nil
inspect -> String
[permalink][rdoc]StringScannerオブジェクトを表す文字列を返します。
文字列にはクラス名の他、以下の情報が含まれます。
使用例
require 'strscan' s = StringScanner.new('test string') s.inspect # => "#<StringScanner 0/11 @ \"test ...\">" s.scan(/\w+/) # => "test" s.inspect # => "#<StringScanner 4/11 \"test\" @ \" stri...\">" s.scan(/\s+/) # => " " s.inspect # => "#<StringScanner 5/11 \"test \" @ \"strin...\">" s.scan(/\w+/) # => "string" s.inspect # => "#<StringScanner fin>"
match?(regexp) -> Integer | nil
[permalink][rdoc]スキャンポインタの地点だけで regexp と文字列のマッチを試します。マッチしたら、スキャンポインタは進めずにマッチした部分文字列の長さを返します。マッチしなかったら nil を返します。
マッチしたサイズは文字単位でなくバイト単位となります。
require 'strscan' def case1(encode) utf8 = "\u{308B 3073 3044}" s = StringScanner.new(utf8.encode(encode)) s.match?(/#{"\u{308B}".encode(encode)}/) end p case1("EUC-JP") #=> 2
使用例
require 'strscan' s = StringScanner.new('test string') p s.match?(/\w+/) #=> 4 p s.match?(/\w+/) #=> 4 p s.match?(/\s+/) #=> nil
matched -> String | nil
[permalink][rdoc]前回マッチした部分文字列を返します。前回のマッチに失敗していると nil を返します。
使用例
require 'strscan' s = StringScanner.new('test string') s.matched # => nil s.scan(/\w+/) # => "test" s.matched # => "test" s.scan(/\w+/) # => nil s.matched # => nil s.scan(/\s+/) # => " " s.matched # => " "
matched? -> bool
[permalink][rdoc]前回のマッチが成功していたら true を、失敗していたら false を返します。
使用例
require 'strscan' s = StringScanner.new('test string') s.matched? # => false s.scan(/\w+/) # => "test" s.matched? # => true s.scan(/\w+/) # => nil s.matched? # => false s.scan(/\s+/) # => " " s.matched? # => true
matched_size -> Integer | nil
[permalink][rdoc]前回マッチした部分文字列の長さを返します。前回マッチに失敗していたら nil を返します。
マッチしたサイズは文字単位でなくバイト単位となります。
require 'strscan' def run(encode) utf8 = "\u{308B 3073 3044}" # るびい s = StringScanner.new(utf8.encode(encode)) s.scan(/#{"\u{308B}".encode(encode)}/) s.matched_size end p run("UTF-8") #=> 3 p run("EUC-JP") #=> 2 p run("Shift_Jis") #=> 2
使用例
require 'strscan' s = StringScanner.new('test string') s.matched_size # => nil s.scan(/\w+/) # => "test" s.matched_size # => 4 s.scan(/\w+/) # => nil s.matched_size # => nil
matchedsize -> Integer | nil
[permalink][rdoc]StringScanner#matched_size と同じです。
このメソッドは は将来のバージョンで削除される予定です。代わりに StringScanner#matched_size を使ってください。
[SEE_ALSO] StringScanner#matched_size
peek(bytes) -> String
[permalink][rdoc]peep(bytes) -> String
スキャンポインタから長さ bytes バイト分だけ文字列を返します。
動作例:
require 'strscan' s = StringScanner.new('test string') s.peek(4) # => "test"
また、このメソッドを実行してもスキャンポインタは移動しません。
StringScanner#peep は将来のバージョンでは削除される予定です。代わりに StringScanner#peek を使ってください。
使用例
require 'strscan' s = StringScanner.new('test string') p s.peek(4) # => "test" p s.peek(20) # => "test string" p s.peek(0) # => "" begin s.peek(-1) rescue ArgumentError => err puts err # negative string size (or size too big) end p s.scan(/\w+/) # => "test" p s.scan(/\s+/) # => " " p s.scan(/\w+/) # => "string" p s.peek(4) # => "" # このメソッドを実行してもスキャンポインタは移動しません。 s = StringScanner.new('test string') p s.peek(4) # => "test" p s.peek(4) # => "test" p s.scan(/\w+/) # => "test" p s.peek(4) # => " str" p s.peek(4) # => " str"
pointer -> Integer
[permalink][rdoc]pos -> Integer
現在のスキャンポインタのインデックスを返します。
使用例
require 'strscan' s = StringScanner.new('test string') s.pos # => 0 s.scan(/\w+/) # => "test" s.pos # => 4 s.scan(/\w+/) # => nil s.pos # => 4 s.scan(/\s+/) # => " " s.pos # => 5
[SEE_ALSO] StringScanner#charpos
pointer=(n)
[permalink][rdoc]pos=(n)
スキャンポインタのインデックスを n にセットします。
使用例
require 'strscan' s = StringScanner.new('test string') p s.scan(/\w+/) # => "test" p s.pos = 1 # => 1 p s.scan(/\w+/) # => "est" p s.pos = 7 # => 7 p s.scan(/\w+/) # => "ring" begin s.pos = 20 rescue RangeError => err puts err #=> index out of range end p s.pos = -4 # => -4 p s.scan(/\w+/) # => "ring"
post_match -> String | nil
[permalink][rdoc]前回マッチを行った文字列のうち、マッチしたところよりも後ろの部分文字列を返します。前回のマッチが失敗していると常に nil を返します。
require 'strscan' s = StringScanner.new('test string') s.post_match # => nil s.scan(/\w+/) # => "test" s.post_match # => " string" s.scan(/\w+/) # => nil s.post_match # => nil s.scan(/\s+/) # => " " s.post_match # => "string" s.scan(/\w+/) # => "string" s.post_match # => "" s.scan(/\w+/) # => nil s.post_match # => nil
pre_match -> String | nil
[permalink][rdoc]前回マッチを行った文字列のうち、マッチしたところよりも前の部分文字列を返します。前回のマッチが失敗していると常に nil を返します。
require 'strscan' s = StringScanner.new('test string') s.pre_match # => nil s.scan(/\w+/) # => "test" s.pre_match # => "" s.scan(/\w+/) # => nil s.pre_match # => nil s.scan(/\s+/) # => " " s.pre_match # => "test" s.scan(/\w+/) # => "string" s.pre_match # => "test " s.scan(/\w+/) # => nil s.pre_match # => nil
reset -> self
[permalink][rdoc]スキャンポインタを文字列の先頭 (インデックス 0) に戻し、マッチ記録を捨てます。
pos = 0と同じ動作です。
require 'strscan' s = StringScanner.new('test string') s.scan(/\w+/) # => "test" s.matched # => "test" s.pos # => 4 s[0] # => "test" s.reset s.matched # => nil s[0] # => nil s.pos # => 0
rest -> String
[permalink][rdoc]文字列の残り (rest) を返します。具体的には、スキャンポインタが指す位置からの文字列を返します。
スキャンポインタが文字列の末尾を指していたら空文字列 ("") を返します。
require 'strscan' s = StringScanner.new('test string') s.rest # => "test string" s.scan(/\w+/) # => "test" s.rest # => " string" s.scan(/\s+/) # => " " s.rest # => "string" s.scan(/\w+/) # => "string" s.rest # => ""
rest? -> bool
[permalink][rdoc]文字列が残っているならば trueを、残っていないならば false を返します。
StringScanner#eos? と逆の結果を返します。
StringScanner#rest? は将来のバージョンで削除される予定です。代わりに StringScanner#eos? を使ってください。
使用例
require 'strscan' s = StringScanner.new('test string') p s.eos? # => false p s.rest? # => true s.scan(/\w+/) s.scan(/\s+/) s.scan(/\w+/) p s.eos? # => true p s.rest? # => false
rest_size -> Integer
[permalink][rdoc]restsize -> Integer
文字列の残りの長さを返します。 stringscanner.rest.size と同じです。
StringScanner#restsize は将来のバージョンで削除される予定です。代わりにStringScanner#rest_size を使ってください。
使用例
require 'strscan' s = StringScanner.new('test string') p s.rest_size # => 11 p s.rest.size # => 11
scan(regexp) -> String | nil
[permalink][rdoc]スキャンポインタの地点だけで regexp と文字列のマッチを試します。マッチしたら、スキャンポインタを進めて正規表現にマッチした部分文字列を返します。マッチしなかったら nil を返します。
使用例
require 'strscan' s = StringScanner.new('test string') p s.scan(/\w+/) #=> "test" p s.scan(/\w+/) #=> nil p s.scan(/\s+/) #=> " " p s.scan(/\w+/) #=> "string" p s.scan(/./) #=> nil
scan_full(regexp, s, f) -> object
[permalink][rdoc]スキャンポインタの位置から regexp と文字列のマッチを試します。
マッチに成功すると、s と f の値によって以下のように動作します。
マッチに失敗すると s や f に関係なく nil を返します。
このメソッドは s と f の組み合わせにより、他のメソッドと同等の動作になります。
使用例
require 'strscan' s = StringScanner.new('test string') p s.scan_full(/\w+/, true, true) #=> "test" p s.scan_full(/\s+/, false, true) #=> " " p s.scan_full(/\s+/, true, false) #=> 1 p s.scan_full(/\w+/, false, false) #=> 6 p s.scan_full(/\w+/, true, true) #=> "string"
[SEE_ALSO] StringScanner#scan StringScanner#skip StringScanner#check StringScanner#match?
scan_until(regexp) -> String | nil
[permalink][rdoc]regexp で指定された正規表現とマッチするまで文字列をスキャンします。マッチに成功したらスキャンポインタを進めて、スキャン開始位置からマッチ部分の末尾までの部分文字列を返します。マッチに失敗したら nil を返します。
使用例
require 'strscan' s = StringScanner.new('test string') s.scan_until(/str/) # => "test str" s.matched # => "str" s.pos # => 8 s.pre_match # => "test "
search_full(regexp, s, f) -> object
[permalink][rdoc]regexp で指定された正規表現とマッチするまで文字列をスキャンします。
マッチに成功すると、s と f の値によって以下のように動作します。
マッチに失敗すると s や f に関係なく nil を返します。
このメソッドは s と f の組み合わせにより、他のメソッドと同等の動作になります。
使用例
require 'strscan' s = StringScanner.new('test string') p s.search_full(/t/, true, true) #=> "t" p s.search_full(/str/, false, true) #=> "est str" p s.search_full(/string/, true, true) #=> "est string"
[SEE_ALSO] StringScanner#scan_until StringScanner#skip_until StringScanner#check_until StringScanner#exist?
skip(regexp) -> Integer | nil
[permalink][rdoc]スキャンポインタの地点だけで regexp と文字列のマッチを試します。マッチしたらスキャンポインタを進めマッチした部分文字列の長さを返します。マッチしなかったら nil を返します。
使用例
require 'strscan' s = StringScanner.new('test string') p s.skip(/\w+/) #=> 4 p s.skip(/\w+/) #=> nil p s.skip(/\s+/) #=> 1 p s.skip(/\w+/) #=> 6 p s.skip(/./) #=> nil
skip_until(regexp) -> Integer | nil
[permalink][rdoc]regexp が一致するまで文字列をスキャンします。マッチに成功したらスキャンポインタを進めて、スキャン開始位置からマッチ部分の末尾までの部分文字列の長さを返します。マッチに失敗したら nil を返します。
使用例
require 'strscan' s = StringScanner.new('test string') s.scan_until(/str/) # => 8 s.matched # => "str" s.pos # => 8 s.pre_match # => "test "
string -> String
[permalink][rdoc]スキャン対象にしている文字列を返します。
使用例
require 'strscan' s = StringScanner.new('test string') s.string # => "test string"
返り値は freeze されていません。
require 'strscan' s = StringScanner.new('test string') s.string.frozen? # => false
なお、このメソッドは StringScanner.new に渡した文字列をそのまま返しますが、この仕様が将来に渡って保証されるわけではありません。この仕様に依存したコードを書かないようにしましょう。
require 'strscan' str = 'test string' s = StringScanner.new(str) s.string == str # => true s.string.eql?(str) # => true (将来は false になる可能性がある)
また、返り値の文字列に対して破壊的な変更もできますが、この操作がスキャン対象の文字列を変更することも保証されません。この仕様に依存したコードを書かないでください。
require 'strscan' str = 'test string' s = StringScanner.new(str) s.string.replace("0123") s.scan(/\w+/) # => "0123" (将来は "test" が返る可能性あり) str # => "0123" (将来は "test string" が返る可能性あり)
string=(str)
[permalink][rdoc]スキャン対象の文字列を str に変更して、マッチ記録を捨てます。
使用例
require 'strscan' str = '0123' s = StringScanner.new('test string') s.string = str # => "0123" s.scan(/\w+/) # => "0123"
unscan -> self
[permalink][rdoc]スキャンポインタを前回のマッチの前の位置に戻します。
require 'strscan' s = StringScanner.new('test string') s.scan(/\w+/) # => "test" s.unscan s.scan(/\w+/) # => "test"
このメソッドでポインタを戻せるのは 1 回分だけです。 2 回分以上戻そうとしたときは例外 StringScanner::Error が発生します。また、まだマッチを一度も行っていないときや、前回のマッチが失敗していたときも例外 StringScanner::Error が発生します。
使用例
require 'strscan' s = StringScanner.new('test string') begin # マッチを一度も行っていないので、例外が発生する。 s.unscan rescue StringScanner::Error => err puts err # 出力例 #=> unscan failed: previous match had failed end p s.scan(/\w+/) # => "test" s.unscan begin # 二回以上戻そうとしたので、例外が発生する。 s.unscan rescue StringScanner::Error => err puts err # 出力例 #=> unscan failed: previous match had failed end p s.scan(/\w+/) # => "test" p s.scan(/\w+/) # => nil begin # 前回のマッチが失敗しているので、例外が発生する。 s.unscan rescue => err puts err # 出力例 #=> unscan failed: previous match had failed end
Id -> String
[permalink][rdoc]StringScanner クラスの詳しいバージョンを文字列で返します。この文字列は Object#freeze されています。
Version -> String
[permalink][rdoc]StringScanner クラスのバージョンを文字列で返します。この文字列は Object#freeze されています。
require 'strscan' StringScanner::Version # => "0.7.0" StringScanner::Version.frozen? # => true