Ключевые слова соответствия регулярному выражению, которые не указаны в кавычках
Как я могу искать ключевые слова, которые не находятся внутри строки.
Например, если у меня есть текст:
Привет, этот текст является примером.
bla bla bla "этот текст находится внутри строки"
"случайная строка" больше текста bla bla bla "foo"
Мне нравится иметь возможность сопоставлять все слова text
, которые не находятся внутри " "
. В другом я хотел бы соответствовать:
![enter image description here]()
note Я не хочу соответствовать тексту, выделенному красным цветом, потому что он находится внутри строки
Возможное решение:
Я работал над этим, и это то, что у меня есть до сих пор:
(?s)((?<q>")|text)(?(q).*?"|)
Обратите внимание, что regex использует оператор if как: (? (предикат) true альтернатива | ложная альтернатива)
поэтому регулярное выражение будет читать:
find "или text. Если вы найдете", то продолжайте выбор, пока не найдете "снова (. *?" ), если вы найдете текст, тогда ничего не сделайте...
когда я запускаю это регулярное выражение, я все равно сопоставляю всю строку. Я задаю этот вопрос для обучения. Я знаю, что могу удалить все строки, а затем искать то, что мне нужно.
Ответы
Ответ 1
Вот один ответ:
(?<=^([^"]|"[^"]*")*)text
Это означает:
(?<= # preceded by...
^ # the start of the string, then
([^"] # either not a quote character
|"[^"]*" # or a full string
)* # as many times as you want
)
text # then the text
Вы можете легко расширить это, чтобы обрабатывать строки, содержащие экраны.
В коде С#:
Regex.Match("bla bla bla \"this text is inside a string\"",
"(?<=^([^\"]|\"[^\"]*\")*)text", RegexOptions.ExplicitCapture);
Добавлено из обсуждения комментариев - расширенная версия (совпадение по строке и дескрипторы дескриптора). Используйте RegexOptions.Multiline
для этого:
(?<=^([^"\r\n]|"([^"\\\r\n]|\\.)*")*)text
В строке С# это выглядит так:
"(?<=^([^\"\r\n]|\"([^\"\\\\\r\n]|\\\\.)*\")*)text"
Поскольку теперь вы хотите использовать **
вместо "
, вот версия для этого:
(?<=^([^*\r\n]|\*(?!\*)|\*\*([^*\\\r\n]|\\.|\*(?!\*))*\*\*)*)text
Пояснение:
(?<= # preceded by
^ # start of line
( # either
[^*\r\n]| # not a star or line break
\*(?!\*)| # or a single star (star not followed by another star)
\*\* # or 2 stars, followed by...
([^*\\\r\n] # either: not a star or a backslash or a linebreak
|\\. # or an escaped char
|\*(?!\*) # or a single star
)* # as many times as you want
\*\* # ended with 2 stars
)* # as many times as you want
)
text # then the text
Так как эта версия не содержит символов "
, более чистая, чтобы использовать литеральную строку:
@"(?<=^([^*\r\n]|\*(?!\*)|\*\*([^*\\\r\n]|\\.|\*(?!\*))*\*\*)*)text"
Ответ 2
Это может быть довольно сложно, но вот один из возможных методов, который работает, убедившись, что существует четное количество кавычек между совпадающим текстом и концом строки:
text(?=[^"]*(?:"[^"]*"[^"]*)*$)
Замените text
на регулярное выражение, которое вы хотите сопоставить.
Rubular: http://www.rubular.com/r/cut5SeWxyK
Пояснение:
text # match the literal characters 'text'
(?= # start lookahead
[^"]* # match any number of non-quote characters
(?: # start non-capturing group, repeated zero or more times
"[^"]*" # one quoted portion of text
[^"]* # any number of non-quote characters
)* # end non-capturing group
$ # match end of the string
) # end lookahead
Ответ 3
Я бы просто жадно сопоставлял текст в кавычках внутри группы, не захватившей их, чтобы отфильтровать их, а затем использовать группу захвата для невостребованного ответа, например:
".*(?:text).*"|(text)
который вы, возможно, захотите немного уточнить для границ слов и т.д. Но это должно заставить вас туда, куда вы хотите пойти, и быть понятным читаемым образцом.