Memoize |
BasicWerk
EC Support
Technique
Facebook
|
20140610123934_factor_regexp |
factor_regexp http://docs.factorcode.org/content/article-regexp-intro.html
R/ の後にスペースを!IN: scratchpad auto-use "foo bar" R/ foo/ "bar" re-replace . 1: Note: Added "regexp" vocabulary to search path "bar bar"
regexp wordssample.txt % less sample.txt Number 1 stack Number 2 words Number 3 regex
re-contains? / matches?ファイルの内容をフィルターしてみる。
IN: scratchpad auto-use "./sample.txt" ascii file-lines [ R/ regex/ re-contains? ] filter 1: Note: Added "io.encodings.ascii" vocabulary to search path --- Data stack: { "Number 3 regex" }
re-contains? はその行に正規表現がマッチする文字列が含まれているか?をチェックするから "Number 3 regex" を取得できる。 行にマッチさせるというコンテキストでは matches? のこの使い方はうまくいかない。 IN: scratchpad auto-use "./sample.txt" ascii file-lines [ R/ regex/ matches? ] filter . { }
matches? を使うのであれば、行全体にマッチしなければいけないから、正しくはこう。 IN: scratchpad auto-use "./sample.txt" ascii file-lines [ R/ ^.+?regex.*?$/ matches? ] filter . { "Number 3 regex" }
つまり sed 的な使い方をするなら re-contains? が適切ということ。
re-replacehttp://docs.factorcode.org/content/article-regexp-options.html
上のページを見ると、あれ? g がない・・・。 案の定、これは動かない。 IN: scratchpad auto-use "foo foo bar baz" R/ foo/g "hoge" re-replace . 1: "foo foo bar baz" R/ foo/g "hoge" re-replace . ^ nonexistent-option name 103 Type :help for debugging help.
おお、なるほど re-replace はデフォルトでグローバルマッチのようだ。 IN: scratchpad auto-use "foo foo bar baz" R/ foo/ "hoge" re-replace --- Data stack: "hoge hoge bar baz" http://docs.factorcode.org/content/word-re-replace,regexp.html
じゃあ、最初のマッチだけ置換するには? 検索した結果、この2つがパーツとして使えそうだ。 IN: scratchpad auto-use "foo foo bar baz" R/ foo/ first-match . T{ slice { from 0 } { to 3 } { seq "foo foo bar baz" } } IN: scratchpad auto-use "foo foo bar baz" R/ xxx/ first-match . f IN: scratchpad auto-use "hoge" 0 3 "foo foo bar baz" replace-slice . "hoge foo bar baz"
first-match は TUPLE を返すから、from と to の値を取り出すにはこんな感じ。 IN: scratchpad auto-use "foo foo bar baz" R/ foo/ first-match from>> . 0 IN: scratchpad auto-use "foo foo bar baz" R/ foo/ first-match to>> . 3
ちょっと寄り道 ボキャブラリの追加自作したボキャブラリを追加するには下記の記事に従って追加すれば良い。
さて、新しい定義を書くための my-regexp ボキャブラリを追加してみる。 IN: scratchpad auto-use USE: tools.scaffold Loading resource:basis/tools/scaffold/scaffold.factor Loading resource:basis/tools/scaffold/scaffold-docs.factor IN: scratchpad auto-use "my-regexp" scaffold-work Creating scaffolding for P" resource:work/my-regexp/my-regexp.factor" Loading resource:work/my-regexp/my-regexp.factor IN: scratchpad auto-use "work" resource-path . "/Applications/factor/work"
シェルに戻って、 % cd /Applications/factor/work % ls README.txt my-regexp/ % cd my-regexp % ls my-regexp.factor % vi my-regexp.factor
my-regexp.factor にワードを追加すると、 IN: scratchpad auto-use USE: my-regexp で、自作のワードが使えるようになる。 また、ボキャブラリファイルに変更を加えた場合は、 IN: scratchpad auto-use "my-regexp" reload で、変更後の定義を反映することができる。 http://oss.infoscience.co.jp/factor/docs.factorcode.org/content/article-first-program-logic.html
re-replace-first を定義する不完全だが最初の定義はこうだ(多分もっとスマートなやり方があるだろうが、なにせ勉強中なので許していただきたい)。 なお、不完全な定義にはワードの末尾に % を付けている。 my-regexp.factorUSING: kernel locals math regexp regexp.private sequences.private accessors sequences ; IN: my-regexp : re-replace-first% ( string regexp replacement -- result ) rot rot over rot rot first-match dup from>> over to>> rot drop rot replace-slice ;
早速使ってみよう。 IN: scratchpad auto-use USE: my-regexp IN: scratchpad auto-use "foo foo bar baz" R/ foo/ "hoge" re-replace-first% . "hoge foo bar baz"
動いた。そして、最初の foo だけが hoge に置換されている。 ただし、この定義は不完全なので、正規表現がマッチしなかったときにエラーになる。 IN: scratchpad auto-use "foo foo bar baz" R/ xxx/ "hoge" re-replace-first% . Generic word from>> does not define a method for the POSTPONE: f class. Dispatching on object: f Type :help for debugging help.
re-replace と同じように置換すべきマッチがなかった時にはオリジナルの文字列をそのまま返したい。 IN: scratchpad auto-use "foo foo bar baz" R/ xxx/ "hoge" re-replace . "foo foo bar baz"
であれば、first-match の結果を、 IN: scratchpad auto-use "foo foo bar baz" R/ xxx/ "hoge" rot rot over rot rot first-match . f --- Data stack: "hoge" "foo foo bar baz" tuple? でチェックして、if に渡せば良い。
まとめると、 ! Copyright (C) 2014 Shin Nakamura. ! See http://factorcode.org/license.txn for BSD license. USING: kernel locals math regexp regexp.private sequences.private accessors sequences ; IN: my-regexp : re-replace-first ( string regexp replacement -- result ) rot rot over rot rot first-match dup tuple? [ dup from>> over to>> rot drop rot replace-slice ] [ drop nip ] if ;
実行してみる。 IN: scratchpad auto-use "my-regexp" reload Loading resource:work/my-regexp/my-regexp.factor IN: scratchpad auto-use "foo foo bar baz" R/ foo/ "hoge" re-replace-first . "hoge foo bar baz" IN: scratchpad auto-use "foo foo bar baz" R/ xxx/ "hoge" re-replace-first . "foo foo bar baz"
http://docs.factorcode.org/content/word-first-match%2Cregexp.html http://docs.factorcode.org/content/word-replace-slice,sequences.html http://docs.factorcode.org/content/article-tuple-examples.html http://docs.factorcode.org/content/word-if,kernel.html http://oss.infoscience.co.jp/factor/docs.factorcode.org/content/article-cookbook-combinators.html
|
© Shin Nakamura/BasicWerk 2014 |