(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'
を実行するしかない。