RegEx для захвата первого закрывающего тега в BBCode - PullRequest
1 голос
/ 08 мая 2019

У меня есть это регулярное выражение ( Regex101 ):

\[tag(?:=(["']?)(.+)\1)?\](.*?)\[\/tag\]

Он допускает четыре различные формы:

[tag=foo]foo[/tag]
[tag="foo"]foo[/tag]
[tag='foo']foo[/tag]
[tag]sdfo[/tag]

Все формы работают, но если я попытаюсь добавить еще [/tag] в конце каждой формы, первая будет продолжать перехват до последнего закрывающего тега (как показано на связанной странице). Можно ли сделать так, чтобы он не продолжал ловить, сохраняя все формы в силе?

Также принимаются любые другие предложения поймать любое другое странное поведение.

Ответы [ 2 ]

2 голосов
/ 08 мая 2019

Просто сделайте .+ не жадным, и все должно работать.

\[tag(?:=(["']?)(.+?)\1)?\](.*?)\[\/tag\]

2 голосов
/ 08 мая 2019

Это выражение может помочь вам получить до первого желаемого [\tag]:

(\[tag?[=A-Za-z0-9\x22\x27]+\])([A-Za-z]+)(\[\/tag\])

Если вы хотите добавить больше границ или уменьшить их, вы можете сделать это. Например, вы можете разрешить больше символов в [] s, если это необходимо.

enter image description here

Graph

Этот график показывает, как будет работать выражение, и вы можете визуализировать свои выражения в этой ссылке . Я добавил взгляд за g, как трюк, чтобы передать [tag]. Это также может быть изменено, я предполагаю, что все ваши входы имеют [tag].

enter image description here

Performance

Этот фрагмент JavaScript показывает производительность этого выражения, используя простой цикл for в 1 миллион раз.

repeat = 1000000;
start = Date.now();

for (var i = repeat; i >= 0; i--) {
	var string = '[tag=foo]foo[/tag]foo[/tag]';
	var regex = /^((\[tag?[=A-Za-z0-9\x22\x27]+\])([A-Za-z]+)(\[\/tag\]))(.*)/g;
	var match = string.replace(regex, "$1");
}

end = Date.now() - start;
console.log("YAAAY! \"" + match + "\" is a match ??? ");
console.log(end / 1000 + " is the runtime of " + repeat + " times benchmark test. ? ");
...