Как найти текст в скобках с некоторыми исключениями с помощью регулярных выражений?
У меня есть регулярное выражение /^\[(text:\s*.+?\s*)\]/mi
, которое в настоящее время работает при захвате текста в скобках, начинающихся с text:
. Вот пример, где он работает:
[text: here is my text that is
captured within the brackets.]
Теперь я хотел бы добавить исключение, чтобы оно допускало определенные скобки, как в следующем случае:
[text: here is my text that is
captured within the brackets
and also include ]
В принципе, мне нужно это, чтобы скобки 
совпадали.
Любая помощь будет принята с благодарностью. Спасибо.
Update:
Вот некоторые случаи, когда текст внутри скобок должен быть сопоставлен:
[text: here is my text that is
captured within the brackets
and also include ]
[text: here is my text that is
captured within the brackets
and also include  and some more text]
[text: ]
![text: cat]
Вот некоторые случаи, когда он не должен совпадать:
[text: here is my text that is
captured within the brackets
and also include ]
[text: here is my text that is
captured within the brackets
and also include ![] (/some/path)]
[text: here is my text that is
captured within the brackets
and also include ! [](/some/path)]
[text: here is my text that is
captured within the brackets
and also include ! [] (/some/path)]
Ответы
Ответ 1
ОК, поэтому вы хотите разрешить либо
- символ, который не является скобкой или
- последовательность
![]
между стартовой и конечной скобками. Это дает вам регулярное выражение
/^\[(text:[^\[\]]*(?:!\[\][^\[\]]*)*)\]/mi
Объяснение:
^ # Start of line
\[ # Match [
( # Start of capturing group
text: # Match text:
[^\[\]]* # Match any number of characters except [ or ]
(?: # Optional non-capturing group:
!\[\] # Match ![]
[^\[\]]* # Match any number of characters except [ or ]
)* # Repeat as needed (0 times is OK)
) # End of capturing group
\] # Match ]
Протестируйте его в прямом эфире на regex101.com.
Ответ 2
Вы можете использовать регулярное выражение, слегка измененное и упрощенное.
str =<<_
[text: here is my text that is
captured within the brackets
and also includes ]
and other stuff
_
r = /
^ # match beginning of string
\[text: # match string
.+? # match one or more characters lazily
\] # match right bracket
/imx # case indifferent (i), multiline (m) and extended/free-spacing (x) modes
PLACEHOLDER = 0.chr
SUBSTITUTE_OUT = '.
scan(r).
map { |s| s.gsub(PLACEHOLDER, SUBSTITUTE_OUT) }
[text: here is my text that is
captured within the brackets
and also includes ]
Обратите внимание, что в регулярном выражении \s*.+?\s*
совпадает с .+?
и (как отмечалось в @sawa) вы можете заменить .+?
на [^\]]+
, и в этом случае вам не понадобится многострочный режим.
Изменить: я обновил SUBSTITUTE_OUT
в свете редактирования вопроса в OP. Это иллюстрирует одно преимущество этого подхода: на регулярное выражение не влияют изменения во внутреннем совпадающем тексте.
Ответ 3
Я использовал отрицательный lookbehind в этом регулярном выражении, чтобы утверждать, что закрывающая скобка не сразу следует за открывающей скобкой:
^\[(text:.+?)(?<!\[)\]
Здесь прохождение.
^ # Start of line anchor.
\[ # Match opening bracket '['
( # Start capturing group 1.
text: # Match 'text:'
.+? # Match any character one or more times lazily.
) # End capturing group 1.
(?<! # Begin negative lookbehind.
\[ # '[' must not preceed the next match.
) # End negative lookbehind.
\] # Match closing bracket.
Здесь демонстрация.
Ответ 4
Я не понимаю, как новый символ строки имеет отношение к тому, что вы описываете, поэтому я удалил ^
.
/\[(text:(?:[^\[\]]|!\[\][/\w]+)+)\]/i
Ответ 5
Я думаю, вам следует попробовать следующее регулярное выражение:
^\[(text:.*?(?<!\[))\]