tag:crieit.net,2005:https://crieit.net/tags/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE/feed 「正規表現」の記事 - Crieit Crieitでタグ「正規表現」に投稿された最近の記事 2021-02-26T06:00:56+09:00 https://crieit.net/tags/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE/feed tag:crieit.net,2005:PublicArticle/16701 2021-02-26T06:00:56+09:00 2021-02-26T06:00:56+09:00 https://crieit.net/posts/Ruby 正規表現エンジン(ロブ・パイクのバックトラック実装)をRubyで写経した <p>元になっているのは『プログラミング作法』に載っている、ロブ・パイクが書いたコード(以下「ロブ・パイク版」)ですが、<a target="_blank" rel="nofollow noopener" href="https://postd.cc/build-your-own-regex/">40行以内で正規表現エンジンを構築 | POSTD</a> の方を見て書いてみました。JavaScript の方が読み慣れているのと、<a target="_blank" rel="nofollow noopener" href="https://github.com/nadrane/build-your-own-regex">リポジトリ</a>にテストコードが用意されていたためです。</p> <pre><code class="ruby">def drop(text, n) text.chars.drop(n).join() end def empty?(str) str.nil? || str.empty? end def match_one(pattern_char, char) return true if empty?(pattern_char) return false if empty?(char) pattern_char == "." || pattern_char == char end # ロブ・パイク版では match def search(pattern, text) if pattern[0] == "^" match(drop(pattern, 1), text) else match(".*" + pattern, text) end end # ロブ・パイク版では matchhere def match(pattern, text) return true if empty?(pattern) return true if empty?(text) && pattern == "$" case pattern[1] # when "?" # match_question(pattern, text) when "*" match_star(pattern, text) else match_one(pattern[0], text[0]) && match(drop(pattern, 1), drop(text, 1)) end end # def match_question(pattern, text) # ( # match_one(pattern[0], text[0]) && # match(drop(pattern, 2), drop(text, 1)) # ) || # match(drop(pattern, 2), text) # end def match_star(pattern, text) ( match_one(pattern[0], text[0]) && match(pattern, drop(text, 1)) ) || match(drop(pattern, 2), text) end </code></pre> <p>たったこれだけで正規表現の基本的な機能が実現できるのすごい&おもしろいですね。</p> <p>ロブ・パイク版では <code>.</code> <code>^</code> <code>$</code> <code>*</code> だけをメタ文字としてサポートする最低限の実装をまず示し、演習問題で <code>?</code> などを追加する流れになっています(なので、上に貼ったコードでは <code>?</code> の部分をコメントアウトしてみました)。</p> <hr /> <p>書籍『ビューティフルコード』では「1章 正規表現マッチャ」をブライアン・カーニハンが書いており、ロブ・パイク版について解説しています。</p> <p>このコードが生まれた経緯について書かれていて、ここもおもしろい。</p> <blockquote> <p> 1998年、ロブ・パイク(Rob Pike)と私は、『プログラミング作法』(原題『The Practice of Programming』、Addison-Wesley刊)という本を執筆していました。(略)<br />  問題は、既存の正規表現パッケージはどれも大き過ぎたということでした。(略)それでは教育用に適しているとは到底言えません。<br />  そこで私はロブに、正規表現の基本的な考え方が読み取れる最小限の、ただしそれでいて有用でつまらなくないパターンが書けるようなパッケージを探そうと提案しました。コードが本の1ページに納まるようなら理想的だと思いました。<br />  ロブは自分の部屋に入って行きました。今思い返してみると、1〜2時間も経たないうちだったと思います。<br /> 彼は30行のCのコードを携えて部屋から出て来ました。そのコードが、『プログラミング作法』の第9章に掲載されているものです。(略)</p> </blockquote> <h1 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h1> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://www.oreilly.co.jp/books/9784873113630/">O'Reilly Japan - ビューティフルコード</a> <ul> <li>英語ですが <a target="_blank" rel="nofollow noopener" href="https://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html">A Regular Expression Matcher(www.cs.princeton.edu)</a> で「1章 正規表現マッチャ」と同じ内容が読めるようです。</li> </ul></li> <li>プログラミング作法 <ul> <li><a target="_blank" rel="nofollow noopener" href="https://asciidwango.jp/post/155982762075">アスキードワンゴ</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://tatsu-zine.com/books/practice-of-programming">達人出版会</a></li> </ul></li> <li><a target="_blank" rel="nofollow noopener" href="https://gihyo.jp/book/2015/978-4-7741-7270-5">正規表現技術入門 ――最新エンジン実装と理論的背景:書籍案内|技術評論社</a> <ul> <li>「5.1 基本的なVM型エンジンの実装」にロブ・パイク版についての説明があります。</li> </ul></li> </ul> sonota486 tag:crieit.net,2005:PublicArticle/16021 2020-08-01T03:02:13+09:00 2020-08-01T03:02:13+09:00 https://crieit.net/posts/PHP-5f245ca597498 各種小説投稿サイトのルビ記法をPHPで実現する <p>「<a target="_blank" rel="nofollow noopener" href="https://qiita.com/8amjp/items/d7c46d9dee0da4d530ef">各種小説投稿サイトのルビ記法をJavaScriptで実現する</a>」<br /> こちらの記事を参考にPHPで関数として作ってみました。</p> <pre><code class="php">function ruby(string $str) { $str = preg_replace('/[||](.+?)(?|((.+?))|\((.+?)\)|《(.+?)》)/u', '<ruby>$1<rt>$2</rt></ruby>', $str); $str = preg_replace('/(\p{Han}+)(?|((.+?))|\((.+?)\)|《(.+?)》)/u', '<ruby>$1<rt>$2</rt></ruby>', $str); return $str; } </code></pre> <p>短歌にルビを振る目的で作ったため、かなりルビが反映されやすくなっています。<br /> 普通の文章にルビを振る場合は、括弧のパターンを減らしたり、括弧がそのまま残る置換を追加したり、括弧内が平仮名カタカナだけになるようにカスタムするといいでしょう。<br /> 気が向いたら更新します。</p> ウラル