Common Lisp の正規表現パッケージ CL-PPCRE を使ってみた。
処理系は CLISP
;; quicklisp で "ppcre" を検索
> (ql:system-apropos "ppcre")
#<SYSTEM arnesi+.cl-ppcre-extras / arnesi+-20120909-darcs / quicklisp 2013-04-20>
#<SYSTEM arnesi.cl-ppcre-extras / arnesi-20101006-darcs / quicklisp 2013-04-20>
#<SYSTEM cl-ppcre / cl-ppcre-2.0.4 / quicklisp 2013-04-20>
#<SYSTEM cl-ppcre-template / cl-unification-20130128-cvs / quicklisp 2013-04-20>
#<SYSTEM cl-ppcre-test / cl-ppcre-2.0.4 / quicklisp 2013-04-20>
#<SYSTEM cl-ppcre-unicode / cl-ppcre-2.0.4 / quicklisp 2013-04-20>
#<SYSTEM optima.ppcre / optima-20130420-git / quicklisp 2013-04-20>
#<SYSTEM parser-combinators-cl-ppcre / cl-parser-combinators-20121125-git / quicklisp 2013-04-20>
;; CL-PPCRE を load
> (ql:quickload :cl-ppcre)
To load "cl-ppcre":
Load 1 ASDF system:
cl-ppcre
; Loading "cl-ppcre"
(:CL-PPCRE)
;; Sample 文字列
> (defvar user-agent "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_6) AppleWebKit/534.28 (KHTML, like Gecko) Chrome/12.0.728.0 Safari/534.28")
;; マッチした部分文字列
> (ppcre:scan-to-strings "M\\S+" user-agent)
"Mozilla/5.0" ;
;; グローバルマッチ
> (ppcre:all-matches-as-strings "M\\S+" user-agent)
("Mozilla/5.0" "Macintosh;" "Mac" "ML,")
;; こんな関数を作っておくと直感的?
(defun m/re/g (re str)
(ppcre:all-matches-as-strings re str))
> (m/re/g "\\d+" user-agent)
("5" "0" "10" "6" "6" "534" "28" "12" "0" "728" "0" "534" "28")
まだまだこれから調べる
参考サイト:
CL-PPCRE - Portable Perl-compatible regular expressions for Common Lisp
第4回 Common Lispライブラリガイド
第2回 Quicklispによるライブラリ環境
#CommonLisp #Lisp #regex #CL-PPCRE #Quicklisp #CLISP
SN 2013/07/20 22:55:01
Archives > CommonLisp_CL-PPCRE_01.html
Gauche の勉強メモ
(define html "<p>This is a a a <em>text</em>.</p>")
;; Perl でいうところの、
;; $foo =~ s/regex/repracement/g;
(regexp-replace-all #/<.+?>/ html "")
;; -> "This is a a a text."
;; グローバルマッチでマッチした文字列のリストを返す
(use gauche.generator)
(define (m/re/g re str)
(map
rxmatch-substring
(generator->list
(grxmatch re str))))
(m/re/g #/\w+/ html)
;; -> ("p" "This" "is" "a" "em" "text" "em" "p")
;; 重複したリストを省く
(delete-duplicates (m/re/g #/\w+/ html))
;; -> ("p" "This" "is" "a" "em" "text")
;; 例えばこんな感じで
;; ブラックリストを作っておき
(define (is_ng? x)
(if (< (string-length x) 2) #t #f))
;; ブラックリストを省く
(remove is_ng? (delete-duplicates (m/re/g #/\w+/ html)))
;; -> ("This" "is" "em" "text")
文字列の出力、日付、format 数値左0埋め。
;; Perl でいうところの
;; open my $out, ">", "file";
(define out (open-output-file "file" :if-exists :supersede))
(format out "This is a text.\n")
;; 日付は srfi-19 を use する
(use srfi-19)
(define today (current-date))
(format out
"And Today is ~4,'0D/~2,'0D/~2,'0D.\n"
(date-year today)
(date-month today)
(date-day today))
;; Perl でいうところの
;; close $out;
(close-output-port out)
;; file の中身は
;; This is a text.
;; And Today is 2013/07/01.
参考:
6.13 正規表現
http://practical-scheme.net/gauche/man/gauche-refj_51.html
9.8.2 Generator operations
http://practical-scheme.net/gauche/man/gauche-refj_82.html#Generator-operations
リストから重複する要素を取り除く - Gaucheクックブック
http://d.hatena.ne.jp/rui314/20070219/p1
6.22.8 出力
http://practical-scheme.net/gauche/man/gauche-refj_60.html#g_t_00e5_0087_00ba_00e5_008a_009b
#Gauche #Scheme #Lisp #Regex
SN 2013/07/01 00:55:19
Archives > 20130630_Gauche_study.html
Gauche のお勉強メモ。文字列処理。
整理しながらなんで全然まとまりないし改善の余地ありありですが。
;; カレントディレクトリを glob して
;; 末尾が .html のファイル名だけを取る
(filter #/\.html$/ (glob "*"))
;; 逆に .html を省く
(remove #/\.html$/ (glob "*"))
;; Perl でいうところの、
;; open my $in, "<", "file_name";
(define in (open-input-file "file_name"))
;; 1行ずつ読み込み
(read-line in)
;; Perl でいうところの、
;; close $in;
(close-input-port in)
;; ファイルの中身を丸っと読み込み
(define str
(call-with-input-file "file_name" port->string))
;; ファイルの中身を行単位でリストにして読み込み
(define lst
(call-with-input-file "file_name" port->string-list))
;; カレントディレクトリにあるファイル名のリスト
(define files (glob "*"))
;; ファイルの内容のリスト
(define values
(map
(lambda (file)
(call-with-input-file file port->string))
files))
;; files と values を組み合わせた alist
(define alist
(map
(lambda (f v)
(cons f v))
files values))
;; いやいや、まとめてやりましょう。
(define alist
(map
(lambda (file)
(cons
file
(call-with-input-file file port->string)))
(glob "*")))
;; ファイルの内容に特定の文字列を含むファイル名
(map
(lambda (lst)
(and (rxmatch #/bla bla bla/i (cdr lst))
(car lst)))
alist)
;; 但し、結果はこんな風に表示されてしまうので
;; -> ("foo.html" "bar.txt" #f #f)
;; マッチしなかった場合は結果から除く
(remove
(lambda (result)
(eq? result #f))
(map
(lambda (lst)
(and (rxmatch #/bla bla bla/i (cdr lst))
(car lst)))
alist))
;; -> ("foo.html" "bar.txt")
参考:
Scheme:テキスト処理
http://practical-scheme.net/wiliki/wiliki.cgi?Scheme:テキスト処理
#Gauche #Scheme #Lisp #IO #Regex #Shell
SN 2013/06/30 00:59:19
Archives > Gauche_text_filter.html
例えばあるHTML文書の中に埋め込まれた画像の情報を抜き出したいとします。
画像には jpg, gif, png が複数入り乱れているとしましょう。
この中から「拡張子が gif でない」画像の URL だけ抽出したいとします。
「〜でない」という条件と、それ以外が複数ある場合に便利なのが「否定の先後読み」という正規表現のテクニックです。
この場合、拡張子は URL の最後に付きますので、一旦 URL 全体を正規表現に飲み込ませて、飲み込んだ文字列のケツがどうなってるか後から確認させますので、「否定の後読み」を使います。
また、正規表現には方言や制限がたくさんありますが、最も自由度の高い正規表現エンジンは Perl に組み込まれたものです。
Perl で「拡張子が gif でない」画像の URL だけ抽出する処理をワンライナーで書くと次のようになります。
$ perl -wnl -e 'print $1 if m/<img src="([^"]+(?<!\.gif))"[^>]*>/imsg' file
(?<!\.gif) この部分が否定の後読み (?<!…) になっています。
[^"]+ でダブルクォーテーション内の文字列 = URL を飲み込んだ後、ちょっと後戻りして拡張子が gif でない、つまりそれ以外の jpg や png にマッチするかどうかを確かめています。
マッチすると "([^"]+(?<!\.gif))" のようにダブルクォーテーションの内側が括弧でくくられているので、正規表現エンジンによって組み込み変数である $1 にキャプチャされ、最後に Perl によって print されます。
#Regex #Perl #HTML
SN 2013/06/26 23:20:34
Archives > 20130621001920_regex_lookbehind_not.html
© 2008-2013 Basic Werk