Замена регулярного выражения только в том случае, если содержится в совпадении с регулярным выражением? - PullRequest
2 голосов
/ 21 мая 2010

У меня есть следующее:

[list]
[*] test
[*] test
[*] test
[/list]

и я хотел бы создать регулярное выражение, которое превращает это в:

<ul>
<li>test</li>
<li>test</li>
<li>test</li>
</ul>

Я знаю регулярное выражение, достаточное для замены простых тегов, но в этом случае мне нужно заменять теги li, только если они содержатся внутри ul. Есть ли способ проверить это перед заменой?

Я использую JavaScript, если это имеет значение.

Ответы [ 2 ]

3 голосов
/ 21 мая 2010

Учитывая текст:

[*] test1

[list]
[*] test2
[*] test3
[*] test4
[/list]

[*] test5

регулярное выражение:

\[\*]\s*([^\r\n]+)(?=((?!\[list])[\s\S])*\[/list])

соответствует только [*] test2, [*] test3 и [*] test4. Но если [list] могут быть вложенными или необходимо проанализировать более широкий набор языков, подобных BB, я выберу правильный синтаксический анализатор.

Для замены замените предложенное мной регулярное выражение:

<li>$1</li>

и затем замените [list] на <ul> и [/list] на </ul> (при условии, что [list] и [/list] используются только для списков и отсутствуют в комментариях, строковых литералах или чем-то еще).

Когда работает следующий фрагмент :

var text = "[*] test1\n"+
    "\n"+
    "[list]\n"+
    "[*] test2\n"+
    "[*] test3\n"+
    "[*] test4\n"+
    "[/list]\n"+
    "\n"+
    "[*] test5\n"+
    "\n"+
    "[list]\n"+
    "[*] test6\n"+
    "[*] test7\n"+
    "[/list]\n"+
    "\n"+
    "[*] test8";

print(text + "\n============================");
text = text.replace(/\[\*]\s*([^\r\n]+)(?=((?!\[list])[\s\S])*\[\/list])/g, "<li>$1</li>");
text = text.replace(/\[list]/g, "<ul>");
text = text.replace(/\[\/list]/g, "</ul>");
print(text);

напечатано следующее:

[*] test1

[list]
[*] test2
[*] test3
[*] test4
[/list]

[*] test5

[list]
[*] test6
[*] test7
[/list]

[*] test8
============================
[*] test1

<ul>
<li>test2</li>
<li>test3</li>
<li>test4</li>
</ul>

[*] test5

<ul>
<li>test6</li>
<li>test7</li>
</ul>

[*] test8

Небольшое объяснение может быть в порядке:

  • \[\*]\s* соответствует подстроке [*], за которой следуют ноль или более пробелов;
  • ([^\r\n]+) сожирает остаток строки и сохраняет его в группе совпадений 1;
  • (?=((?!\[list])[\s\S])*\[/list]) гарантирует, что в каждой группе совпадений 1 должна быть подстрока [/list] перед без , при этом [list]

EDIT

Или, что еще лучше, сделайте, как Гамбо предлагает в комментарии к этому ответу: сопоставьте все [list] ... [/list] и затем замените все [*] ... в этих.

2 голосов
/ 21 мая 2010

Вот лучший подход к предложению Барта К.:

  • найти все [list] … [/list]
  • для каждого матча, найти все [*] в нем

Это обеспечит замену только [*] в [list] … [/list].

Код:

str.replace(/\[list]([\s\S]*?)\[\/list]/g, function($0, $1) {
    return "<ul>" + $1.replace(/^ *\[\*] *(.*)/gm, "<li>$1</li>") + "</ul>";
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...