regex-tool 20170104.1118(in MELPA)
A regular expression evaluation tool for programmers

概要

あなたは

  • 正規表現を組み立てるのに苦労していませんか?
  • マッチさせようと思った正規表現がうまく動かなくて困っていませんか?
  • 正規表現のグルーピングは使いこなせていませんか?

それならば、
ここで紹介する
regex-tool.el
おすすめします。

作者は20年以上
Emacs開発に携わっている
現Emacsメンテナの
John Wiegley氏です。

標準の M-x re-builder
コンセプトは似ていますが、

こちらはターゲットとなる
文字列を指定して、
正規表現を組み立てる点が
違います。

M-x regex-tool を起動すると、

  1. 新たなフレームが現れ
  2. 上中下のウィンドウに分割される
    • 上→ *Regex*バッファ(正規表現を書くバッファ)
    • 中→ *Text*バッファ(ターゲットとなる文字列のバッファ)
    • 下→ *Groups*バッファ(マッチ箇所を表示するバッファ)
  3. *Regex*と*Text*を自由に編集すると
  4. *Regex*を書き換えると*Text*と*Groups*がリアルタイムに更新される
  5. C-c C-k で終了

のような流れで正規表現を組み立てます。

本設定では方言に合わせて

M-x regex-tool-emacs
Emacs正規表現
M-x regex-tool-perl
Perl正規表現
M-x regex-tool-ruby
Ruby正規表現

で起動できるようにしています。

20170110060554.png
Fig1: M-x regex-tool-ruby

なお、
ソースコードは
平易に書かれているため、

Emacs Lisp中級者ならば
解読に挑戦してみましょう。

インストール

パッケージシステムを初めて使う人は
以下の設定を ~/.emacs.d/init.el の
先頭に加えてください。

(package-initialize)
(setq package-archives
      '(("gnu" . "http://elpa.gnu.org/packages/")
        ("melpa" . "http://melpa.org/packages/")
        ("org" . "http://orgmode.org/elpa/")))

初めてregex-toolを使う方は
以下のコマンドを実行します。

M-x package-install regex-tool

アップグレードする方は、
以下のコマンドでアップグレードしてください。
そのためにはpackage-utilsパッケージが必要です。

M-x package-install package-utils (初めてアップグレードする場合のみ)
M-x package-utils-upgrade-by-name regex-tool

Perlにも対応

regex-tool.el
Emacsの正規表現だけでなく
Perlにも対応しています。

正規表現の情報を
表示するスクリプトは
regex-tool.el に内蔵されているため、
Perlインタプリタがあれば動作します。

カスタマイズ変数
regex-tool-backend
emacs/perlを切り替えられますが、

本設定では
コマンドを定義して
両方とも使えるようにしておきます。

regex-tool.el
Perl対応になっているのは、

regex-render-perl 関数が
正規表現と文字列を受け取って
S式を返す関数になっているからです。

(defun regex-render-perl (regex sample)
  (with-temp-buffer
    (insert (format "@lines = <DATA>;
$line = join(\"\", @lines);
print \"(\";
while ($line =~ m/%s/mg) {
  print \"(\", length($`), \" \", length($&), \" \";
  for $i (1 .. 20) {
    if ($$i) {
      my $group = $$i;
      $group =~ s/([\\\\\"])/\\\\\\1/g;
      print \"(\", $i, \" . \\\"\", $group, \"\\\") \";
    }
  }
  print \")\";
}
print \")\";
__DATA__
%s" regex sample))
   (call-process-region (point-min) (point-max) "perl" t t)
   (goto-char (point-min))
   (read (current-buffer))))

評価させると、
こんな感じになります。

$ (regex-render-perl "perl" "I love perl.")
((7 4))
$ (regex-render-perl "p(e)(r)l" "I love perl.")
((7 4
    (1 . "e")
    (2 . "r")))
$ (regex-render-perl "(.)a" "I love papa and mama.")
((7 2
    (1 . "p"))
 (9 2
    (1 . "p"))
 (11 2
     (1 . " "))
 (16 2
     (1 . "m"))
 (18 2
     (1 . "m")))

文字列全体に対して何度もマッチさせ、それぞれ

  • マッチ開始オフセット
  • マッチ部分の長さ
  • 部分文字列をインデックスつきのコンスセルのリスト

を返していることがわかります。

Rubyにも対応させてみる

それならば、
Rubyでも同様のことをすれば
Rubyの正規表現(Onigmo)にも
対応できます。

Rubyの正規表現を使いたければ、

  1. regex-render-ruby を定義し
  2. regex-render-perl:override アドバイスをかける

の手順でできます。

上記の情報を使えば、
他言語にも対応できます。

設定 170110054733.regex-tool.el(以下のコードと同一)

(defun regex-render-ruby (regex sample)
  (with-temp-buffer
    (insert (format "
line = DATA.read
re = /%s/
print '('
pos = 0
while md=re.match(line,pos)
  printf '(%%d %%d', md.begin(0), md.end(0)-md.begin(0)
  puts
  md.captures.each_with_index{|c,i| printf '(%%d . %%s)', i+1,c.inspect }
  pos = md.end(0)
  puts ')'
end
print ')'
__END__
%s" regex sample))
    (insert (format ""))
   (call-process-region (point-min) (point-max) "ruby" t t)
   (goto-char (point-min))
   (read (current-buffer))))

(defun regex-tool-emacs ()
  (interactive)
  (setq regex-tool-backend 'emacs)
  (regex-tool))
(defun regex-tool-perl ()
  (interactive)
  (setq regex-tool-backend 'perl)
  (advice-remove 'regex-render-perl 'regex-render-ruby)
  (regex-tool))
(defun regex-tool-ruby ()
  (interactive)
  (setq regex-tool-backend 'perl)
  (advice-add 'regex-render-perl :override 'regex-render-ruby)
  (regex-tool))

実行方法

$ wget http://rubikitch.com/f/170110054733.regex-tool.el
$ emacs -Q -f package-initialize -l 170110054733.regex-tool.el


本日もお読みいただき、ありがとうございました。参考になれば嬉しいです。