Как сопоставить что-то с регулярным выражением, которое не находится между двумя специальными символами?
У меня есть строка вроде этого:
a b c a b "a b" b a "a"
Как я могу сопоставить каждый a
, который не является частью строки, ограниченной "
? Я хочу сопоставить все, что здесь смело:
a bc a b "ab" b a "a"
Я хочу заменить эти соответствия (или скорее удалить их, заменив их пустой строкой), поэтому удаление цитируемых частей для сопоставления не будет работать, потому что я хочу, чтобы они оставались в строке. Я использую Ruby.
Ответы
Ответ 1
Предполагая, что кавычки правильно сбалансированы и нет экранированных кавычек, тогда легко:
result = subject.gsub(/a(?=(?:[^"]*"[^"]*")*[^"]*\Z)/, '')
Это заменяет все a
пустой строкой тогда и только тогда, когда существует четное число котировок перед совпадающим a
.
Объяснение:
a # Match a
(?= # only if it followed by...
(?: # ...the following:
[^"]*" # any number of non-quotes, followed by one quote
[^"]*" # the same again, ensuring an even number
)* # any number of times (0, 2, 4 etc. quotes)
[^"]* # followed by only non-quotes until
\Z # the end of the string.
) # End of lookahead assertion
Если вы можете избежать кавычек в кавычках (a "length: 2\""
), это все еще возможно, но будет сложнее:
result = subject.gsub(/a(?=(?:(?:\\.|[^"\\])*"(?:\\.|[^"\\])*")*(?:\\.|[^"\\])*\Z)/, '')
Это по существу такое же регулярное выражение, как и выше, только подставляя (?:\\.|[^"\\])
для [^"]
:
(?: # Match either...
\\. # an escaped character
| # or
[^"\\] # any character except backslash or quote
) # End of alternation
Ответ 2
js-coder, воскресив этот древний вопрос, потому что у него было простое решение, которое не было упомянуто. (Нашел свой вопрос, проведя некоторое исследование для заданий по поиску регулярных выражений.)
Как вы можете видеть, регулярное выражение действительно крошечное по сравнению с регулярным выражением в принятом ответе: ("[^"]*")|a
subject = 'a b c a b " a b " b a " a "'
regex = /("[^"]*")|a/
replaced = subject.gsub(regex) {|m|$1}
puts replaced
Смотрите эту живую демонстрацию
Ссылка
Как сопоставить шаблон, за исключением ситуаций s1, s2, s3
Как сопоставить шаблон, если...
Ответ 3
Полномасштабное решение регулярных выражений для любовника regex, не заботясь о производительности или читаемости кода.
В этом решении предполагается отсутствие синтаксиса экранирования (с синтаксисом escaping, a
in "sbd\"a"
считается как внутри строки).
псевдокод:
processedString =
inputString.replaceAll("\\".*?\\"","") // Remove all quoted strings
.replaceFirst("\\".*", "") // Consider text after lonely quote as inside quote
Затем вы можете сопоставить текст, который вы хотите, в processedString
. Вы можете удалить вторую замену, если вы рассматриваете текст после одиночной цитаты как внешнюю цитату.
ИЗМЕНИТЬ
В Ruby регулярное выражение в коде выше будет
/\".*?\"/
используется с gsub
и
/\".*/
используется с sub
Чтобы решить проблему замены, я не уверен, возможно ли это, но стоит попробовать:
- Объявить счетчик
- Используйте регулярное выражение
/(\"|a)/
с функцией gsub и функцией поставки.
- В функции, если совпадение
"
, затем увеличивайте счетчик и возвращайте "
в качестве замены (в основном, без изменений). Если совпадение a
, проверьте, равен ли счетчик: если даже укажите свою заменяющую строку; в противном случае просто поставьте все, что соответствует.