Bye Bye Moore

猫マンション建築の野望を胸に零細事業主として資本主義の荒波に漕ぎ出したアラサー男の技術メモ

標準ライブラリ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:パケット例は以下のサイトを参考にさせてもらいました。