#ruby #regex #gsub #ruby-1.8.7
#рубиновый #регулярное выражение #gsub #рубин-1.8.7 #ruby #ruby-1.8.7
Вопрос:
У меня есть немного кода для экранирования двойных кавычек из строки, которая может включать предварительно экранированные кавычки; например:
This is a "string"
Используя следующий код с Ruby 1.8.7p374:
string.gsub!(/([^\])"/, '1"')
Тем не менее, я получаю забавный крайний случай, когда пытаюсь использовать его в следующей строке: ab""c
=> ab""c
. Я бы ожидал, что он избежал обеих кавычек.
Это определенно не большая проблема, но мне стало любопытно.
Это ошибка с моим выражением лица? gsub
Ошибка / особенность?
(В более новых версиях Ruby это, вероятно, можно было бы легко решить, используя негативные отзывы, но, похоже, они не поддерживаются в этой версии).
Комментарии:
1. Проблема заключается в перекрывающихся выражениях,
([^\])
они не будут соответствовать"
только что замененным вами.2. Непонятно, что у вас есть. Если
"
в конце находится символ двойной кавычки, то это будет описано как"
. Но тогда,"
перед этим, это означало бы, что у вас есть символ обратной косой черты, за которым следует символ двойной кавычки, который будет описан\"
как экранированный. Это действительно то, что у вас есть?
Ответ №1:
Требование соответствия
несимвольному означает, что регулярное выражение должно использовать этот символ, а также кавычки. gsub
Совпадения также не могут перекрываться.
Вы правы, что предварительное утверждение исправит это. Но без этого у вас есть несколько вариантов в Ruby 1.8.7.
-
Повторяйте, пока не будет сделано никаких замен (
gsub!
возвращаетnil
, если совпадений не было):loop { break unless string.gsub!(/([^\])"/, '1"') }
-
Для 1.8.7 у вас нет предварительных утверждений. Но вы можете изменить строку, использовать предварительные утверждения для внесения изменений, а затем изменить ее обратно:
string = string.reverse.gsub(/"(?!\)/, '"\').reverse
Ответ №2:
Ваше регулярное выражение также не будет работать, если в начале строки есть кавычка, например "ab""c
, преобразуется в "ab""c
. Причина этого аналогична вашему случаю с двойными кавычками.
После gsub
сопоставления b"
и замены оно продолжается с последнего совпадения, просматривая следующее "
, но не просматривая ранее использованные символы.
Возможно, вы сможете решить вашу проблему с помощью lookbehind в более новых версиях Ruby, но это не решит проблему с началом строки. Способ исправить это — использовать G
привязку (которая доступна в Ruby 1.8.7), которая соответствует тому месту, где закончилось предыдущее совпадение или в начале строки. Итак, вы ищете a "
, который либо сразу после косой черты, либо находится в начале текущего совпадения (это означает, что a "
только что было сопоставлено, или это начало строки). Что-то вроде этого:
string.gsub!(/([^\]|G)"/, '1"')
Это преобразует строку "ab""c
в "ab""c
.