Upgrade to Pro — share decks privately, control downloads, hide ads and more …

POSIX文字クラスでの躓き

muryoimpl
August 27, 2023

 POSIX文字クラスでの躓き

Kanazawa.rb meetup#132 祝11周年 LT大会での LT。
Ruby (Onigmo) ではエンコーディングによって、POSIX文字クラス名の見た目と挙動に差が出ちゃうよ、という話。

muryoimpl

August 27, 2023
Tweet

More Decks by muryoimpl

Other Decks in Programming

Transcript

  1. ある日の irb にて • 環境は、 ruby 3.2.2 (2023-03-30 revision e51014f9c0)

    [x86_64-linux] • 以下のコードを入力してみたが、イメージしていたものと違う動作をした。 irb(main):001:0:> /[[:alnum:]]+/.match?(“10”) : true irb(main):002:0:> /[[:alnum:]]+/.match?(“あ0”) : true [[:alnum:]] で “あ” で true ? なぜ?から調査は始まった。
  2. 正規表現のページを確認すると • [:alnum:] は POSIX 文字クラスまたはPOSIXブラケット というもの。 また、[:^クラス名:]という記法でその否定を意味する。 (以下、POSIXブラケットと呼ぶ) •

    似たような機能を持つ記法に Unicode プロパティというものもある。 ◦ \p{property-name} ◦ \p{^property-name} (否定) ◦ 具体例: \p{Letter}
  3. Unicodeプロパティ • Rubyのデフォルトエンコーディングは UTF-8 irb(main):001:0:> "あ".encoding : #<Encoding:UTF-8> • alnum

    は Unicodeプロパティの Letter | Mark | Decimal_Number に相当する。こ れは Ruby の正規表現のページにも同じ記載があった。 • Mark と Decimal_Number はぼんやりとイメージが湧くが、Letter の範囲は? ◦ https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp にて、Unocodeプロパティを入力して範 囲を確認してみる
  4. Unicodeプロパティ \p{Letter} • ひらがな、漢字等かなりの広範囲の”文字”が含まれていた。 • Onigmo のドキュメントにあったとおり、エンコーディングが Unicode の場合におい て、

    実はほとんどすべての文字をカバーしてしまう • つまり、alnum は alphabet と number ではない。 Letter が alphabet のみなら ず、広範囲の文字をカバーしてしまうため • 英数字のみならば、/ [a-zA-Z0-9]+/.match?(“あ”) みたいに、明示的に範囲を指定 するか • 正規表現のページのオプションによると、/(?a:[[:alnum:]]+)/.match?("あ") のよう に、オプションで動作が変えられるようだ
  5. まとめ • Rubyのデフォルトエンコーディングは UTF-8 、正規表現でPOSIXブラケットを見た ままのイメージで使うと痛い目に遭う • Onigmo の POSIXブラケットはエンコーディングによって挙動が変わるため、使う場

    合は文字列のエンコーディングを意識する必要がある • 正規表現のみならず、処理を実装するときは失敗パターンも確認しましょう • ChatGPT さんの意見を鵜呑みにしてはいけない