Почему String # gsub дублирует контент? - PullRequest
9 голосов
/ 16 августа 2011
s = "#main= 'quotes'
s.gsub "'", "\\'" # => "#main= quotes'quotes"

Кажется, это неправильно, я ожидаю получить "#main= \\'quotes\\'"

, когда я не использую escape-символ, тогда он работает, как и ожидалось.

s.gsub "'", "*" # => "#main= *quotes*"

Такдолжно быть что-то связанное с экранированием.

Использование ruby ​​1.9.2p290

Мне нужно заменить одинарные кавычки на обратную косую черту и кавычку.

Еще больше несоответствий:

"\\'".length # => 2
"\\*".length # => 2

# As expected
"'".gsub("'", "\\*").length # => 2
"'a'".gsub("'", "\\*") # => "\\*a\\*" (length==5)

# WTF next:
"'".gsub("'", "\\'").length # => 0

# Doubling the content?
"'a'".gsub("'", "\\'") # => "a'a" (length==3)

Что здесь происходит?

Ответы [ 3 ]

17 голосов
/ 16 августа 2011

Вас запутывает особенность \' внутри строки замены регулярного выражения :

\0, \1, \2, ... \9, \&, \`, \', \+
Подставляет значение, соответствующее n-му сгруппированному подвыражению или всему совпадению, до или после совпадения, или самой высокой группе.

Поэтому, когда вы говорите "\\'", двойное значение \\ становится просто одной обратной косой чертой, и в результате получается \', но это означает «Строка справа от последнего успешного совпадения». Если вы хотите заменить одиночные кавычки на экранированные одинарные кавычки, вам нужно экранировать больше, чтобы преодолеть особенность \':

s.gsub("'", "\\\\'")

Или избегайте зубочисток и используйте блочную форму:

s.gsub("'") { |m| '\\' + m }

Вы столкнетесь с подобными проблемами, если попытаетесь избежать обратных кавычек, знака плюс или даже одной цифры.

Общий урок здесь состоит в том, чтобы предпочесть блочную форму gsub для всего, кроме самых тривиальных замен.

2 голосов
/ 16 августа 2011
s = "#main = 'quotes'

s.gsub "'", "\\\\'"

Так как \ это \\ эквивалент, если вы хотите получить двойную обратную косую черту, вы должны поставить четыре из них.

1 голос
/ 16 августа 2011

Вам также нужно убежать от \ *:

s.gsub "'", "\\\\'"

Выходы

"#main= \\'quotes\\'"

На внешнем форуме найдено хорошее объяснение:

Ключевым моментом для понимания ИМХО является то, что обратный слеш замена строк. Таким образом, всякий раз, когда кто-то хочет иметь буквальный обратная косая черта в замещающей строке, нужно убежать от нее и, следовательно, иметь [две] обратные косые черты. По совпадению, обратный слеш также особенный в строка (даже в одной строке в кавычках). Так что вам нужно два уровня экранирование, делает 2 * 2 = 4 обратной косой черты на экране для одного литерала замена обратной косой черты.

источник

...