- Ruby / Rails関連
READ MORE
|
と部分マッチのワナ.*
や.+
がバックトラックで不利な理由主にRubyを中心としながらも、なるべく一般的な形で正規表現を解説しています。誤りやお気づきの点がありましたら@hachi8833までどうぞ🙇。
Unicode文字コードポイントの表記方法も、正規表現ライブラリによってまちまちです。そもそもUnicode文字コードポイントで表せない正規表現ライブラリもたまにあります。困ったことです。
まず、Unicodeという規格本体に文字集合(character set)というものがあります。その文字集合内の位置を表すのがコードポイント(code point: 符号点)です。
手元のかな漢字変換にある「文字パレット」を開くと、Unicodeの文字集合とそのコードポイントを見ることができます。U+00F9
みたいなのがコードポイントで、16進数です。
ここで重要なのは、コードポイントはUnicodeそのものの規格なので、エンコードがUTF-8だろうと16だろうと32だろうとコードポイントは変わらないという点です。U+00F9
の00F9
はUnicodeのどのエンコードでも同じです。
Unicode文字コードポイントはほとんどが4桁です。
しかし、後から足された文字の中にはコードポイントが5桁や6桁のものがあります。かつてこれがMySQLの有名な「寿司ビール問題」を引き起こしました。特に最近はUnicodeに絵文字が大量に追加されているので、これまでこの種の問題に関心が薄かった英語圏も絵文字の普及とともにやっと真剣に考えてくれるようになったのはありがたいことです。
ここからが本題です。
Unicodeの規格ではU+00F9
というような表記が用いられていますが、正規表現ライブラリ(というよりライブラリを使うプログラミング言語)によって表記方法はまちまちです。以下はほんの一例です。
\uFFFF
[\u{FFFF}]
、[\uFFFF]
、\uFFFF
、\u{FFFF}
[\uFFFF]
、\uFFFF
[\x{FFFF}]
、\x{FFFF}

{}
があってもなくても許容します{}
を許容しません{}
が必須ですつまり、たとえばPythonとPerlの両方で同じ正規表現を動かそうとするとここが最も移植の障害になります😭。
コードポイントは正規表現の中に直接書くこともできますが、私は個人的に[\uFFFF]
などのように文字セット[ ]
の中に入れて書くのが好みです。次に説明するUnicode文字クラスと書式が揃って気持ちいいという理由です。
そして意外に思われるかもしれませんが、私はそもそも[\uFFFF]
のようなコードポイント記法をほぼまったく用いません。主な理由は上のように言語/ライブラリでの非互換性が大きいということと、コメントなしでは意味不明になりがちな視認性の悪さです。私は正規表現のメンテナンス性を重視するので、一度書いたら忘れてもいい正規表現ならともかく、後で細かく調整する正規表現は未来の自分が読んでくじけない書き方を常に目指しています。
駅の名前を全部覚えるみたいにコードポイントを覚えるくらいなら、文字セット[ ]
の中に文字を直接書きます。
円周率なら3.1415926535897932384626までは覚えちゃいましたが。
以下の記事をご覧いただければおわかりいただけると思いますが、文字セット[ ]
の中は別世界なので、相当特殊な文字であっても[ ]
の中に安心して書けます。
ただ、特に[-ー-─―‐]
のような「ハイフンと紛らわしい文字のセット」のような正規表現では、本来の-
(U+002D、ASCIIだと2D)を文字セットの冒頭または末尾以外には置かないよう心がけています。-
を途中に置くと「両側の文字の範囲」になってしまうので。
また、一部の結合文字のように、エディタやIDEやターミナルで入力すると挙動がおかしくなる特殊な文字があります。そういう場合には、仕方なくコードポイントで書くこともあります。
Unicode文字クラスのプロパティは、\p{なんちゃら}
という形で表記します(pはプロパティのことでしょうね)。マルチリンガルな正規表現で非常に有用性が高いのが特徴です。これが使えるライブラリは高機能と認めてよいと思います。
\p{なんちゃら}
は比較的最近の機能であるためか、文字コードポイントなんかと違って、主要な言語での記法のブレが少ないのがありがたい点です🙏。
\p{なんちゃら}
の「なんちゃら」の部分には、以下の3種類を指定できます。
[\p{L}]
(記号/約物/スペースでない)あらゆる文字(letter)、[\p{Zs}]
(スペース)、[\p{N}]
(あらゆる数字)、[\p{No}]
(漢数字や①などの数字)などHan
(漢字)、Katanaka
(長音を除くカタカナ)、Latin
(ラテン文字: 要するにアルファベット)などIn_CJK_Unified_Ideographs
など上の表のリンクをクリックすると、それぞれの全リストを参照できます。
[\p{N}]
とすると、[\p{Nd}]
(数値用の数字)と[\p{Nl}]
(ローマ字などの数字)と[\p{No}]
(漢数字や分数などの数字)といったサブカテゴリを一発で表せるので便利です。CJK Unified Ideographs
などと書かれていたりするので、自分でIn_
を付けたりスペースを_
に置き換えるなどしてIn_CJK_Unified_Ideographs
のような形にする必要があります。面倒です😇。
なお、Unicode文字クラスで言う文字(letter)は「記号やスペースといった約物(punctuation)や数値(number)などでないもの」という補集合的な意味で捉える必要があります。
[\p{L}]
や[\p{N}]
のような一般カテゴリは、マッチする範囲が非常に大きいので注意が必要です。余分なマッチを呼び込んでいないか、使う前によーくチェックしましょう。
[\p{Zs}]
はありとあらゆるスペース文字にマッチするので、ゼロ幅スペースのようないたずらにしか使えないようなスペース文字すら捉えられます。うまく使えば非常に有用です。
カタカナにマッチさせたい場合、たとえば[\p{Katakana}]+
だけでは長音ー
が含まれないので注意が必要です。[\p{Katakana}ー]+
などのように長音も忘れず含めましょう。
[\p{Katakana}][\p{Katakana}ー]+
のように冒頭の長音を排除したいところです。[\p{Katakana}ーー゙゚]+
/のように半角の濁点と半濁点と長音ー゙゚
も加える必要があります(Rubular)。
私は日本語を相手にする正規表現をよく使います。その中で多用している有用な文字クラスは、[\p{Han}]+
(漢字にマッチ)、[\p{Hiragana}]+
(ひらがなにマッチ)[\p{Katakana}ー]+
(カタカナにマッチ)の3つです。
[\p{Han}]+
/で漢字にマッチ(Rubular)[\p{Hiragana}]+
/でひらがなにマッチ(Rubular)[\p{Katakana}ー]+
/でカタカナにマッチ(Rubular)これらは誤動作の心配もなく、#3で紹介したような[一-龠]
や[ぁ-ん]
といった文字セットよりずっと洗練されています。私にとって、ないと生きていけない機能であり、これらが使えない正規表現ライブラリに用はありません。
文字セット同士の差分を取れると、正規表現を簡潔に書くうえで非常に有用です。詳しくは以下の記事をご覧ください。
|
と部分マッチのワナ.*
や.+
がバックトラックで不利な理由正規表現ってちょっと覚えるだけでなく書き方が変わるので、いざ必要になった時に思い出せるように記憶の片隅に入れておきたい。
そしてRubular最高。はじめての正規表現とベストプラクティス https://t.co/tpNDUJDVDQ
— two_sann (@two_sann) February 21, 2019
READ MORE
READ MORE
READ MORE