EmacsのバッファでPerl one-liner を手軽につかう

(defun perl-command (command)
  (interactive "sInput perl one-liner: ")
    ;; replace ' with \x27.
    (when (string-match "'" command)
      (setq command (replace-regexp-in-string "'" "\\\\x27" command)))
    (if (and mark-active transient-mark-mode)
        (if (string-match "print" command)
            (shell-command-on-region
             (region-beginning) (region-end) (concat "perl -ne \'" command "\'") nil t)
          (shell-command-on-region 
           (region-beginning) (region-end) (concat "perl -pe \'" command "\'") nil t))
      (insert (shell-command-to-string (concat "perl -e \'" command "\'")))))

Emacsのバッファでリージョンがアクティブなときにはそのリージョンに対して perl -pe 'command' あるいは perl -ne 'command' を実行して置き換える。
リージョンがアクティブでない時には単に perl -e 'command' を実行してカーソル位置に挿入します。

コマンドラインオプションの -pe と -ne の判断はcommandがprint文を含んでいるか否かで判定します。
というのも次の形で使うことが多いので。

perl -pe 's/foo/bar/g'
perl -ne 'print if /hoge/'


そして定義したperl-commandを適当なキーにバインド。例えば

(global-set-key (kbd "C-x p") 'perl-command)


使い方は、perl-command を実行するとミニバッファに

Input perl one-liner: 

と表示されるのでコマンドの部分だけを入力してリターンでOK.

例えばリージョンを指定した場合、ミニバッファで

print uc

とすると、すべて大文字にする(printを含むので perl -ne 'print uc'を実行)

print if /hoge/ 

hoge を含む行のみ表示(perl -ne 'print if /hoge/'を実行)

s/foo/bar/g; s/baz/hoge/g 

fooをbarに置換した後、bazをhogeに置換。(print を含まないのでperl -pe 's/foo/bar/g; s/baz/hoge/g'を実行)
正規表現はセミコロンで区切って続けて書けます。

問題点

正規表現や文字列の中にprintという単語がある場合 -pe で実行するつもりでも -ne で実行されてしまう。そういう場合はまじめに

C-u M-| perl -pe 'command'

を実行するしかない。