LoginSignup
2
0

Ruby/StringScanner: scan_full, search_full 系メソッドの整理

Last updated at Posted at 2023-05-28

たまに 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 のような別オブジェクトに状態を管理させた方がよい、となるんですよね。オブジェクト指向プログラミングのある種の典型だと思います。

2
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0