Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

標準ライブラリstrscanで文字列の複雑な切り分けも楽々

xbee = "7E001210010013A200409821A5FFFE0000544553545E"

てなXBeeの16進数で記述されたパケットがあったとします。*1
二文字毎に切り出すのであれば、Stringクラスのscanを使えば簡単です。

> xbee.scan(/\h\h/)
#=> ["7E", "00", "12", "10", "01", "00", "13", "A2", "00", "40", "98", "21", "A5", "FF", "FE", "00", "00", "54", "45", "53", "54", "5E"]

これを更にZigBeeの規格通りに切り分けるとなると、結構大変です。
そこで役立つのがRuby標準配布ライブラリのstrscan。
Ruby環境があれば安定して使える子であるにも関わらず、非常に強力です。

使い方

初期化

strscanを読み込み、StringScannerクラスのインスタンスを起こします。

> require 'strscan'
#=> true

> s = StringScanner.new(xbee)
#=> #<StringScanner 0/44 @ "7E001...">

scan

scanは基本となるメソッドで、一致した部分を返してくれます。
Stringのものと違い、読み込んだ位置まで覚えていてくれます。
次は続きから開始できます。
C言語っぽいですね。

> start = s.scan(/\w{2}/)
#=> "7E"

> start
#=> "7E"

> datalength = s.scan(/\w{4}/)
#=> "0012"

> type = s.scan(/\w{2}/)
#=> "10"

> id = s.scan(/\w{2}/)
#=> "01"

> addr = s.scan(/\w{16}/)
#=> "0013A200409821A5"

...

> chksum = s.scan(/\w{2}/)
#=> "5E"

#> s.scan(/.+/)
=> nil

eos?

末尾に至った場合は「eos?」メソッドがtrueを返します。

> s.eos?
=> true

*1:パケット例は以下のサイトを参考にさせてもらいました。