Стековая переменная

Стековая переменная - новая возможность в Proxomitron Naoko-4. Нормально Proxomitron поддерживает 10 переменных от \0 до \9. В большинстве случаев этого достаточно, но может случится, что вам понадобится больше.

Например, использование выражений "+" и "++" совпадения с повторяющейся последовательностью совпадений. Что если вы захотите забрать каждый встретившийся элемент в отдельную переменную? Взгляните на пример, который совпадает с каждой частью пути URL:

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

Часть выражения (*/)+ ищет совпадение для каждого участка URL, но как сохранить каждую часть в отдельную переменную? Для этого используем cтековую переменную. Он использует специальный символ "\#", который по аналогии с \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:
Matching:
Replace:
<Sometag\s*>
(\#(attr1|attr2|attr3)=$AV(*))+ \#
\@

1. Первый раз \# ловит текст до первого удаляемого атрибута.
2. Последующие проходы ловят текст между текущим и последующим атрибутом.
3. Последний \# ловит все то, что осталось после последнего атрибута или весь тег, если совпадений найдено не было.

Сохраняет только выбранные атрибуты (и отбрасывает все остальные)

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

Этот пример противоположен предыдущему, но очень похож. Он отбрасывает все, за исключением атрибутов, которые вы хотите сохранить. здесь только одна переменная, сохраняющая атрибут и его значение.

Замена значений атрибутов чем-нибудь другим

Bounds:
Matching:


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

Этот пример несколько сложнее. Он использует команду $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 ) 

для выборочной замены как атрибута, так и значения. (Кстати, это даже лучше, поскольку элементы списка индексируются и поиск происходит быстрее.)