今週、正規表現で作成したコードについて要点をふりかえります。
【目的】
ボウリングのスコア計算をするため(旧ルール)。
【要件】
10回目までの投球結果を示した文字列。
9回目までの投球でXが出現していれば、直後に0を挿入した文字列にしたい。
【作業内容】
Rubularを使って実際に意図した変換ができるか記述を確かめながら正規表現を作ります。
正規表現については以下のサイトを参照にさせていただいています。
Rubularの使い方についても詳しい解説があります。
初心者歓迎!手と目で覚える正規表現入門・その1「さまざまな形式の電話番号を検索しよう」
【作成したコード(抜粋)】
modified_scores = add_0_after_markX.gsub(/(?<=.{18})X0/, 'X')
正規表現とは
正規表現について、自分なりの言葉で表現できないか考えてみます。
「正規」とは、正式の規則。
正式とは、簡略化されていない正当と認められた方式。
wikipedia では、
とされています。
初めてこの説明を読んだときにはいまいちぴんとこなかったのですが、今は前よりは「なるほど」と思える説明です。
正規表現を活用してみて初めて、理解できる表現のように感じます。
用語の原義にこだわるより「どういった用途で使うか」という観点で表現したほうが伝わりやすそうです。
(そもそも正規表現の説明が必要となるのは、その活用が必要となるシーンにほぼ限定されていますしね。)
そのように考えると、「複数のバリエーションがある文字列を探したいとき、コンピューターに探し方のヒントを教える方法」となりそうです。
コンピューターは人間と違って文脈や意図の汲み取りができないので、細かく明確(厳密)な指示が必要です。
しかし、標的の文字列にはいくつかのバリエーションが考えられるケースがあります。
バリエーションに応じて一つづつ指示をしなくても、コンピューター側が認識できる表現方法で条件を伝えることで一括で処理できる便利なもの。
現状の私の理解で正規表現を表現するなら上記となりそうです。
なお、検索した結果条件を満たした場合を「マッチする」、マッチした条件を表示させることを「キャプチャ(補足)」と表現するのが慣例のようです。
正規表現で使われる用語
今回のコードを用語の意味もあわせてふりかえります。
modified_scores = add_0_after_markX.gsub(/(?<=.{18})X0/, 'X')
gsub(<検索したい文字>、<変換したい文字>)
正規表現は / / で囲まれた部分です。
一旦1字ずつ確認。
( ) カッコ内の条件でマッチするものを探す
? 直前の文字列が1字、または0。量指定子
. 任意の一文字
{ } 文字の個数を限定量指定子。{18} だと18個。
量指定子
文字の個数を限定するメタ文字。
メタ文字
本来の意味とは異なる特別な意味や役割を持つ文字のこと。
肯定の後読み
今回は「肯定の後読み」というテクニックを使っています。
(?<=xxx) と指定すると、xxxの直後の位置にマッチします。
(?<=.{18})X0 なら18文字の直後にX0があるところを検知します。
「肯定」は指定する文字列が「ある」というのが条件、「後読み」は指定する文字列が後ろにある条件を指していると考えると覚えやすいです。
つまり、(?<=.{18})X0 は「19字目にX,20字目に0がある文字列をマッチせよ」です。
「先読み・後読み」については以下の記事を参考にさせていただきました。
今回のプログラム設計について、振り返ると。
わざわざXのあとに0を挿入して1フレームを2投球に揃えずとも、「Xが出現した次の投球は1投球目とする」という設計にしてもよかったなぁと思えました。