Конфликты из-за наличия одной и той же группы в начале и в конце - PullRequest
2 голосов
/ 08 мая 2019

У меня есть регулярное выражение, которое должно поймать:

[=foo]
[="foo"]
[='foo']

Начало и конец должны быть одинаковыми, поэтому я собираюсь перехватить кавычки и вызвать их в конце с \ 1.Знак вопроса, на котором он используется, также не принимает кавычек:

\[=(['\"]?)(.+)\1\]

Работает нормально, если я пытаюсь сделать это в одной строке, но когда я пытаюсь написать что-нибудь еще и вызвать скобку закрытия, она будет соответствовать до этой скобки,Некоторые примеры поведения: https://regex101.com/r/4qYzyS/1

У кого-нибудь есть решение?Чтобы соответствовать 3 шаблонам, которые я хочу без конфликтов?Благодаря.

Ответы [ 4 ]

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

Вы можете просто сделать это, используя это выражение:

(\[=)(.+)(\])

Демо

enter image description here

Если вы хотите добавить границы вместо использования (.+), вы можете использовать выражение и добавить любые возможные символы, которые могут быть между [], возможно, что-то похожее на :

(\[=)([A-z\s\x22]+)(\])

enter image description here

Graph

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

enter image description here

код

Этот код показывает, как выражение будет работать в Python:

# -*- coding: UTF-8 -*-
import re

string = "[=foo]Lorem ipsum] with anything else that you wish"
expression = r'((\[=)([A-z\s\x22]+)(\]))'
match = re.search(expression, string)
if match:
    print("YAAAY! \"" + match.group(1) + "\" is a match ??? ")
else: 
    print('? Sorry! No matches! Something is not right! Call 911 ?')

выход

YAAAY! "[=foo]Lorem ipsum]" is a match ???

Тест производительности

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

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

for (var i = repeat; i >= 0; i--) {
	var string = "[=foo]Lorem ipsum] with anything else that you wish";
	var regex = /((\[=)([A-z\s\x22]+)(\]))(.*)/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. ? ");
2 голосов
/ 08 мая 2019

Сделайте точку не жадной, т.е. используйте (.+?).Кроме того, вы можете отключить вторую группу захвата или просто полностью удалить ее.Например, работает следующий шаблон:

\[=([\"']?).+?\1\]

Демо

Вот пример скрипта Python:

input = "[=\"foo\"]\n[=\"Lorem ipsum\"]\n\n[=foo]Lorem ipsum]";
for match in re.finditer(r"\[=([\"']?).+?\1\]", input):
    print match.group(0)

[="foo"]
[="Lorem ipsum"]
[=foo]
1 голос
/ 08 мая 2019

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

Regex Demo после отключения режима DOTALL

enter image description here

Кроме того, в вашем третьем примере я не уверен, хотите ли вы, чтобы ваше регулярное выражение было полным или нет, но на случай, если вы намереваетесь соответствовать только [=foo], а не [=foo]Lorem ipsum], тогда вы должны использовать [^[\]]+ вместо .+ в своем регулярном выражении.

Кроме того, поскольку вы, похоже, хотите соответствовать вашей строке, если она либо окружена "или ' или ничего с обеих сторон, тогда вы должны также включить " и ' в класс отрицанных символов, чтобы ваше регулярное выражение не совпадало с вводом, подобным этому [="foo].В целом правильное регулярное выражение, которое вы должны использовать, это:

регулярное выражение, которое вы должны использовать точно

1 голос
/ 08 мая 2019

Если вы сделаете (.+) не жадным как (.+?), вы предотвратите выпадение остальной части строки:

\[=([\"']?)(.+?)\1\]/
              ^
...