たまに StringScanner を使おうとすると「似てるメソッドがいろいろあるけどどのメソッドで何ができるんだっけ?」「○○がしたいんだけどどのメソッドを使えばいいんだっけ?」となりがちで、一度チートシート的に整理しておきたかったのでした。
「スキャンポインタとは何か?」といったあたりについてはリファレンスマニュアルで説明されていますので、そちらを見てください。
scan_full 系
- マッチを試みる位置: スキャンポインタの位置のみ
- 返り値の範囲: マッチした部分
メソッド | スキャンポインタを進める | 返り値 |
---|---|---|
scan | YES | 文字列 |
skip | YES | 文字列の長さ |
check | no | 文字列 |
match? | no | 文字列の長さ |
スキャンポインタの扱いと返り値の種類の組み合わせで4パターン。
この組み合わせは scan_full
メソッドの引数 s, f の指定に対応しており、上記の4つのメソッドは scan_full
の糖衣のようなメソッドと捉えることができます。
または、「これら4つのメソッドを個別に覚えていなくても scan_full
メソッドについて知っていれば用が足りる」という見方もできるかもしれません。
search_full 系
- マッチを試みる位置: スキャンポインタの位置より後ろも含む
- 返り値の範囲: スキャン開始位置からマッチした部分の末尾までの部分
メソッド | スキャンポインタを進める | 返り値 |
---|---|---|
scan_until | YES | 文字列 |
skip_until | YES | 文字列の長さ |
check_until | no | 文字列 |
exist? | no | 文字列の長さ |
scan_full
系のメソッドとの規則性が見てとれますね。大きなところでは「マッチを試みる位置」が違っています。
scan_full
系のメソッドと同様に、これら4つの組み合わせは search_full
メソッドの引数 s, f の指定に対応しています。
観点まとめ
(1) 大まかには「マッチさせたい位置」の違いで scan_full 系と search_full 系の2つに分けられる。
(2) 細かく見ると
- マッチさせたい位置: スキャンポインタの位置のみ(scan_full 系) or スキャンポインタの位置より後ろも含む(search_full 系)
- スキャンポインタ: 進める or 進めない
- 返り値: 文字列 or 文字列の長さ
の組み合わせにより全部で 8 パターンに分けられる。
8パターンの中から用途に応じて使いたいものを選ぶことになります。
たとえば
- マッチを試みる位置は「スキャンポインタの位置より後も含む」としたい
- スキャンポインタを進めたい
- (スキャン開始位置からマッチした部分の末尾までの部分文字列の)長さが欲しい
だったら skip_until
または search_full(regexp, true, false)
を使えばよいわけです。
メモ
たまに StringScanner を使おうとすると「似てるメソッドがいろいろあるけどどのメソッドで何ができるんだっけ?」「○○がしたいんだけどどのメソッドを使えばいいんだっけ?」となりがちで、一度チートシート的に整理しておきたかったのでした。
そのうち書くつもりだったのを @okuramasafumi さんの記事を見て思い出し、よい機会なので書いてみました。
以前 JavaScript で StringScanner みたいなものを使いたくなったことがあって、私も簡単なものを書いたことがありました。
ベタに書くとスキャンポインタなどの状態を操作するコードがロジックのあちこちに散らばって鬱陶しいことになり、それをどうにかしようとすると StringScanner のような別オブジェクトに状態を管理させた方がよい、となるんですよね。オブジェクト指向プログラミングのある種の典型だと思います。