Метод Ruby gsub со строкой '+'

Я нашел интересную вещь в рубине. Кто-нибудь знает, почему такое поведение?

попробовал '+'.gsub!('+', '\+') и ожидал "\\+", но получил ""(пустая строка)

Обычно, когда публикуется подобное странное поведение, все недоумевают, пока кто-нибудь не объяснит, почему такое поведение на самом деле ожидается. Потом все кивают вертикально, одни хлопают себя по лбу, другие делают вывод, что ответ на самом деле очевиден, а иногда и говорят об этом в комментарии. (Я был озадачен, пока не прочитал ответ Сильвио и документ String#gsub.)

Cary Swoveland 03.12.2022 22:46

PRD RSD, @tadman упомянул основные причины, по которым изображения кода не приветствуются в SO. Есть и другая причина: ссылки могут быть сломаны в будущем. Во многих случаях это сделало бы вопрос неполным; здесь урон меньше. Если вы используете только текст, вы можете быть уверены, что ваш полный вопрос навсегда останется в SO.

Cary Swoveland 04.12.2022 03:32
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Шаг 1: Создание приложения Slack Чтобы создать Slackbot, вам необходимо создать приложение Slack. Войдите в свою учетную запись Slack и перейдите на...
0
2
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

gsub реализован, после некоторой косвенности, как rb_sub_str_bang в C, который вызывает rb_reg_regsub.

Теперь предполагается, что gsub позволяет замещающей строке содержать обратные ссылки. То есть, если вы передаете регулярное выражение в качестве первого аргумента, и это регулярное выражение определяет группу захвата, тогда ваша строка замены может включать \1, чтобы указать, что эта группа захвата должна быть помещена в эту позицию.

Такое поведение, очевидно, все еще происходит, если вы передаете обычную строку, не являющуюся регулярным выражением, в качестве шаблона. В вашей дословной строке, очевидно, не будет групп захвата, так что в данном случае это немного глупо. Но попытка заменить, например, + на \1 в строке + даст пустую строку, так как \1 говорит, что нужно перейти к первой группе захвата, которая не существует и, следовательно, бессодержательна "".

Теперь вы можете подумать: + — это не число. И ты будешь прав. Вы заменяете + на \+. В вашей замещающей строке разрешено несколько других обратных ссылок. Я не смог найти никакой официальной документации, где это прописано, но исходный код работает вполне нормально. Подводя итог коду:

  • Цифры от \1 до \9 относятся к пронумерованным группам захвата.
  • \k<...> относится к именованной группе захвата, имя которой заключено в угловые скобки.
  • \0 или \& относятся ко всей совпадающей подстроке, поэтому (\0) в качестве строки замены будет заключать совпадение в круглые скобки.
  • Обратная косая черта, за которой следует обратная кавычка (я понятия не имею, как написать это, используя уценку StackOverflow), относится ко всей строке до совпадения.
  • \' относится ко всей строке после совпадения.
  • \+ относится к последней группе захвата, то есть к группе с наибольшим номером.
  • \\ — буквальная обратная косая черта.

(Большинство из них основаны на переменных Perl с похожим именем)

Итак, в ваших примерах

  • \+ как говорится в заменяющей строке «взять последнюю группу захвата». Группы захвата нет, поэтому вы получаете пустую строку.
  • \- не является допустимой обратной ссылкой, поэтому она заменена дословно.
  • \ok также не является обратной ссылкой, поэтому заменено дословно.
  • В \\+ Ruby съедает первую последовательность обратной косой черты, поэтому фактическая строка во время выполнения — \+, что эквивалентно первому примеру.
  • Для \\\+ Ruby обрабатывает первую последовательность обратной косой черты, поэтому мы получаем \\+ к тому времени, когда функция замены ее увидит. \\ — это буквальная обратная косая черта, а + больше не является частью escape-последовательности, поэтому мы получаем \+.

Вы можете сослаться на документ для String#gsub.

Cary Swoveland 03.12.2022 22:45

Вот «официальная документация», которую вы искали «Методы замены строк» ​​ и «Специальные глобальные переменные Regexp»

engineersmnky 05.12.2022 18:43

Другие вопросы по теме