CL-PPCRE は本当に便利だし、動作も早い。マジでありがたいパッケージだ。
 
こいつが Common Lisp になかったら、本気で開発環境を Perl から Common Lisp に移行しようとは考えなかったと思う。
 
ただ、CL-PPCRE は多機能過ぎるから「生」の状態だとどの関数を使おうか迷ってしまう。
 
あと単純に関数名が長くて覚えていられない・・・。
 
というわけで、普段は自分がよく使う機能だけに絞り込んで簡単な関数に纏めて使ってる。
 
 
要点
 

  • マッチなら
    (m "foo.+?bar" 'isg str)

    置換なら

    (s "foo.+?bar" "" 'isg str)

    みたいに書きたい

  • マッチの先頭を見つけたいだけなら scan-to-strings、グローバルマッチなら all-matches-as-strings
  • 置換も同様に、先頭マッチの置換なら regex-replace、グローバルなら regex-replace-all
  • フラグで普段使うのはぶっちゃけ g i m s の4つだ。g は前述の関数を切り替えることで対処。
    他フラグは正規表現の scanner を作る( create-scanner する)際に、それぞれ対応する下記パラメータの値をセットする
    i -> :case-insensitive-mode
    s -> :single-line-mode
    m -> :multi-line-mode

 
で、上の内容を関数化する。
 

 
;; http://weitz.de/cl-ppcre/
(ql:quickload 'cl-ppcre)
 
;; --- 補助関数、ここから ---
(defun get_regex_flag_string (flags)
 (if (stringp flags)
  flags
  (if (and (symbolp flags) flags) ; nil -> ""
   (string-downcase (symbol-name flags))
   "")))
 
#+cl-ppcre
(defun make-scanner (regex flags)
 (let ((f (get_regex_flag_string flags))) 
  (cl-ppcre:create-scanner
    regex
    :single-line-mode (find #\s f :test 'equal)
    :multi-line-mode (find #\m f :test 'equal)
    :case-insensitive-mode (find #\i f :test 'equal))))
 
(defun include-g-flag-p (flags)
 (let ((f (get_regex_flag_string flags))) 
  (find #\g f :test 'equal)))
 
;; --- 補助関数、ここまで ---
 
;; --- 以下目的の関数 ---
 
#+cl-ppcre
(defun m (regex flags target-str)
  (let ((s (make-scanner regex flags))) 
   (if (include-g-flag-p flags)
     (cl-ppcre:all-matches-as-strings s target-str)
     (cl-ppcre:scan-to-strings s target-str))))
 
#+cl-ppcre
(defun s (regex rep flags target-str)
  (let ((s (make-scanner regex flags)))
   (if (include-g-flag-p flags)
     (cl-ppcre:regex-replace-all s target-str rep)
     (cl-ppcre:regex-replace s target-str rep))))
 

 
こうしておくと、だいぶ気軽に正規表現が使えるようになる。
 
 
 

§1554 · Posted By · 4月 27, 2014 · Development · Tags: , , , , , , · [Print]