置換スタック
Previous Back to contents Next

「置換スタック」は、Proxomitron Naoko-4 の新機能です。標準で Proxomitron は \0 から \9 までの10個の変数をサポートしています。大抵の場合はこれで十分ですが、もしかしたらこれでは足りないことがあるかもしれません。

こんな例を考えてみましょう。「+」や「++」を使って、マッチの繰り返しにマッチさせる、と。もし、このときにマッチしたアイテムを、それぞれ別々の変数に代入したいとしたらどうしますか? 具体的な例を見てみましょう。これは、URL の path の部分にマッチさせる繰り返しの表現です...

http://(*/)+*.html

(*/)+ という表現は、URLの各部分にマッチします ── しかし、これらのマッチした部分を別々の変数に代入するにはどうしたらいいでしょう? そこで置換スタックが生まれました。これは特別なキャラクタである「\#」を、「\0」から「\9」までと同じように、マッチした値を取り込むために使用します。置換スタックの場合は、「\#」が呼ばれるごとに、マッチした値を最大 100 個まで「スタック」に蓄えます。これが置換テキストで使用されると、「先に入ったものが先に出ていく」法則に従って蓄えられたものを出力していきます。これを使えば、先のマッチはこのように書くことができます...

http://(\#/)+\#.html

ここで以下のような置換テキストが使用されたとすると...

"\# \# \# \# \# \# \#"

下のような URL は...

http://this/is/a/test/of/the/stack.html

このように置換されます...

"this is a test of the stack.html"

(...)+ でマッチした値は、それぞれスタックに蓄えられています。そして、それでも残ったものが最後の「\#」で取り込まれています。他の変数と同様に、スタック変数を括弧の直後に置くことで、括弧内でマッチしたものを取り込むために使用することができます。たとえば...

http://(*/)\#+\#

この表現を使用すると、結果は以下のようになります...

"this/ is/ a/ test/ of/ the/ stack.html"

置換テキストでは、さらに別の特別なエスケープとして「\@」を使用することができます。これはスタックに蓄えられたものを全て、順番に出力します( \#\#\#\#\#\#\#\#... を使用するようなものです)。実際のところ、殆どの場合ではこちらを使うことになるでしょう。

代表的な使い方の例...

\# は、次のように考えることもできます。つまり、これは \1、\2、\3 などとまったく同じ働きで、ただ複数回呼ばれた場合には、その内容を入れ替えるのではなくスタックに蓄えていくのだ、と。ここでいくつか実例を見てみましょう...

タグのアトリビュート(属性)を取り除く:

Bounds: <Sometag\s*>
Matching: (\#(attr1|attr2|attr3)=$AV(*))+ \#
Replace: \@

  1. 最初の「\#」で、取り除きたいアトリビュートの前にあるものを取り込みます(もしあれば)。
  2. ループを作成し、そこから次の取り除きたいアトリビュートまでの間にあるものを取り込みます。
  3. 終わりの \# で、最後のアトリビュートの後ろに残ったもの、あるいはアトリビュートが全くマッチしなかった場合にはタグ全体を取り込みます。

特定のアトリビュートだけを残す(そして他のを全部振り落とす):

Bounds: <Sometag\s*>
Matching: (*((attr1|attr2|attr3)=$AV(*) )\#)+ *
Replace: <Sometag \@>

これは上の反対ですが、とてもよく似ています。残したいアトリビュート以外のものを全部捨てるものです。こちらでは、アトリビュートと値を取り込むのに、ハッシュ(訳註:「#」の読み方です)が一つしかありません。

属性値を何か別のものに置き換える:

Bounds: <Sometag\s*>
Matching: (\#((attr1=)\#foo$SET(\#=bar)|
(attr2=)\#black$SET(\#=white)|
(attr3=)\#one$SET(\#=zero)))+ \#
Replace: \@

これはやや複雑です。通常のマッチに加えて、$SET(\#=...) コマンドを使用していることに注目してください。これを使えば少々興味深いことができます。

上記の例では、まずマッチさせるアトリビュートを探しています。それが見つかると、まずその名前をスタックに入れ、それからその値にマッチしようとします。そして、それが探している値だった場合には、set を使って、かわりに新しい値をスタックに入れます。加えて、マッチしなかったものも取り込んで、失われないようにしています。また、リストで別々の属性値を置換することもできます。たとえば...

(\#$LST(AttributeReplace))+ \#

これを以下のようなリストや...

#
# Sample attribute replacement list
#
(attr1=)\#foo$SET(\#=bar)
(attr2=)\#black$SET(\#=white)
(attr3=)\#one$SET(\#=zero) 

あるいはこんなリストで使用します...

#
# Sample attribute replacement list two
#
attr1=foo $SET(\#=attr1=bar )
attr2=black $SET(\#=attr2=white )
attr3=one $SET(\#=attr3=zero ) 

このようにして、アトリビュートとその値を選択的に何か別のものに置き換えます。(実は、リストではアイテムを「ハッシュ」することができ、結果的にマッチが速くなるので、こちらの方が優れています。)


Return to main index