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 words

 

sample.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-replace

 

http://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
 

 

 

ちょっと寄り道 ボキャブラリの追加

自作したボキャブラリを追加するには下記の記事に従って追加すれば良い。

日本語:

http://oss.infoscience.co.jp/factor/docs.factorcode.org/content/article-first-program-start.html

 

英語:

http://docs.factorcode.org/content/article-first-program-start.html

 

さて、新しい定義を書くための 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.factor
 
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 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