Regex: Как получить все содержимое внутри тега # [НЕКОТОРЫЙ ТЕКСТ ЗДЕСЬ] - PullRequest
3 голосов
/ 02 февраля 2009

Я работаю над простой функцией замены токенов нашего продукта. Я почти решил все проблемы, но я упустил одну вещь. Токен должен поддерживать атрибуты, а атрибут также может быть токеном. Это часть большого проекта. надеюсь, что вы можете помочь.

Начальный тег - "**#[**", а конечный тег - "**]**". Скажем, # [FirstName], # [LastName], # [Age, WhenZero = "нераскрытый"].

Сейчас я использую это выражение "\#\[[^\]]+\]". У меня это работает, но это не удалось на этом входе:

blah blah text here...
**#[IsFreeShipping, WhenTrue="<img src='/images/fw_freeshipping.gif'/>
<a href='http://www.hellowebsite.net/freeshipping.aspx'>$[FreeShipping]</a>"]**
blah blah text here also...

Он терпит неудачу, потому что он первым начинает], на этом он останавливается. Возвращает:

*#[IsFreeShipping, WhenTrue="<img src='/images/fw_freeshipping.gif'/>
<a href='http://www.hellowebsite.net/freeshipping.aspx'>$[Product_FreeShipping]*

Мой желаемый результат должен быть

*#[IsFreeShipping, WhenTrue="<img src='/images/fw_freeshipping.gif'/>
<a href='http://www.hellowebsite.net/freeshipping.aspx'>$[FreeShipping]</a>"]*

Ответы [ 7 ]

1 голос
/ 02 февраля 2009

Ваше регулярное выражение соответствует в точности тому, что указано в вашем условии: начните с открывающей квадратной скобки и сопоставьте все до первой закрывающей квадратной скобки.

Если вы хотите сопоставить вложенные квадратные скобки, вам нужно точно указать, что действительно при вложении. Например, вы можете сказать, что квадратные скобки могут быть вложены в кавычки.

1 голос
/ 02 февраля 2009

Это небольшая граница для регулярного выражения, поскольку оно зависит от контекста, но все же ...

#\[(\](?=")|[^\]])+\]

должен это сделать.

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

Если бы эта же квадратная скобка была где-то внутри атрибута, это было бы намного сложнее ...


Преимущество в выражении lookahead заключается в том, что вы можете указать регулярное выражение с нефиксированной длиной соответствия.
Поэтому, если за закрывающей квадратной скобкой атрибута не следует двойная кавычка, а следует другое известное выражение, вы просто обновляете часть предпросмотра:

#\[(\](?=</a>")|[^\]])+\]

будет соответствовать только второй закрывающей квадратной скобке, поскольку за первой следует </a>".

Конечно, любое жадное выражение (.*]) не будет работать, так как оно не будет соответствовать второй закрывающей квадратной скобке, а last . (Имеется в виду, что если имеется более одного промежуточного звена ], он будет проанализирован.)

0 голосов
/ 04 февраля 2009

Это работает для вашего образца:

#\[(?:[^\]$]+|\$(?!\[)|\$\[[^\[\]]*\])*\]

Предполагается, что внутренние квадратные скобки не могут сами содержать квадратные скобки. Если внутренние токены также могут содержать токены, вам, вероятно, не повезло. Некоторые разновидности регулярных выражений могут обрабатывать рекурсивные структуры, но получающиеся регулярные выражения отвратительны даже по стандартам регулярных выражений. : D

Это регулярное выражение также рассматривает '$' как особенное, только если за ним следует открывающая квадратная скобка. Если вы хотите запретить его использование в противном случае, удалите второй вариант: |\$(?!\[)

0 голосов
/ 02 февраля 2009

Можно написать регулярное выражение для примера, который вы дали, но в целом это не удается. Одно регулярное выражение не может работать для произвольных вложенных выражений.

Ваш пример показывает, что ваш DSL уже имеет условия if. Вскоре он может развиться в полный по Тьюрингу язык.

Почему бы вам не использовать существующий язык шаблонов, такой как Язык шаблонов Django :

Ваш пример:

blah blah text here... #[IsFreeShipping, 
WhenTrue="<img src='/images/fw_freeshipping.gif'/>
<a href='http://www.hellowebsite.net/freeshipping.aspx'>$[FreeShipping]</a>"]
blah blah text here also...

Использование языка шаблонов Django:

blah blah text here... {% if IsFreeShipping %}
<img src='/images/fw_freeshipping.gif'/>
<a href='http://www.hellowebsite.net/freeshipping.aspx'>{{ FreeShipping }}</a>
{% endif %} blah blah text here also...
0 голосов
/ 02 февраля 2009

Мне было бы интересно узнать, если я ошибаюсь, но если я правильно помню, вы не можете сделать это с помощью регулярных выражений. Для меня это похоже на язык Dyck, и вам понадобится автомат для принятия выражений. Но я должен признать, что я не совсем уверен, верно ли это для расширенной формы регулярного выражения, подобной той, что предоставляется Perl.

0 голосов
/ 02 февраля 2009

Если вы ожидаете только одно совпадение в любом заданном входе, вы можете просто разрешить жадное совпадение:

/#\[.*\]/

Если вы ожидаете мультипликаторы, у вас есть проблема, потому что у вас больше нет обычного текста. Вам нужно каким-то образом избежать внутренних скобок.

(Regex - глубокий предмет - вполне возможно, что у кого-то есть лучшее решение)

0 голосов
/ 02 февраля 2009

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

В этом случае вашему регулярному выражению, вероятно, следует попытаться заменить $ [FreeShipping] на его значение, прежде чем оценивать токен большего размера, содержащий предложение if.

Возможно, вы сможете найти способ замены токенов значения, таких как $ [FreeShipping], перед токенами без $, предшествующих токену

Это примерно, но не совсем

http://en.wikipedia.org/wiki/Multi-pass_compiler против http://en.wikipedia.org/wiki/One-pass_compiler

Запись этого в одном регулярном выражении не обязательно будет быстрее, чем в нескольких простых регулярных выражениях. Все, что нужно сделать в regex - это разбор абстрактных строк.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...