Project

General

Profile

Actions

Misc #16091

closed

gsub

Misc #16091: gsub

Added by thiaguerd (thiago feitosa) over 6 years ago. Updated over 6 years ago.

Status:
Closed
Assignee:
-
[ruby-core:94218]

Description

a = "test ?" b = "?" c = "\\&" a.gsub(b,c) 

Updated by thiaguerd (thiago feitosa) over 6 years ago Actions #1

  • Subject changed from sub to gsub

Updated by nobu (Nobuyoshi Nakada) over 6 years ago Actions #2

  • Description updated (diff)
  • Status changed from Open to Feedback

Updated by shyouhei (Shyouhei Urabe) over 6 years ago Actions #3 [ruby-core:94223]

Really sorry that I have to say I don't understand this report at all. Please tell us about your problem a bit more in detail.

Updated by thiaguerd (thiago feitosa) over 6 years ago Actions #4 [ruby-core:94233]

shyouhei (Shyouhei Urabe) wrote:

Really sorry that I have to say I don't understand this report at all. Please tell us about your problem a bit more in detail.

the replacement doesn't happen

try in python and see the diff

a = "test ?" b = "?" c = "\\&" a.replace(b,c) 

Updated by chrisseaton (Chris Seaton) over 6 years ago Actions #5 [ruby-core:94234]

@thiaguerd I don't understand - the String#replace method only takes one argument - you're calling it with two so that's not going to work for a start. Secondly, the method doesn't replace occurrences of one string with another, which is what I think you think it does. It replaces the whole string with another string.

https://ruby-doc.org/core-2.6.3/String.html#method-i-replace

So your code doesn't work because that's just not what this method does or is documented to do in Ruby.

Updated by jeremyevans0 (Jeremy Evans) over 6 years ago Actions #6 [ruby-core:94235]

  • Status changed from Feedback to Rejected

This is not a bug. Ruby treats \& in a replacement string specially, representing the entire matched string (note that "\\&" is the same as '\&'):

"test ?".sub("?", "1\\&2") => "test 1?2" 

So "\\&" as a replacement string means perform the replacement, but use the same text as what you are replacing.

If you want to replace something with \&, you need to double the backslashes:

puts "test ?".sub("?", "\\\\&") # output: test \& 

If you want to replace something with &, use no backslashes:

puts "test ?".sub("?", '&') # output: test & 

Python does not handle \& specially, which is why the behavior is different.

Updated by thiaguerd (thiago feitosa) over 6 years ago Actions #7 [ruby-core:94238]

include ERB::Util def r puts "Enter original" a = gets.chomp puts "Enter a pattern to replace" b = gets.chomp puts "Enter a replacement" c = gets.chomp puts "a: #{a}" puts "b: #{b}" puts "c: #{c}" c = html_escape c puts "c escaped: #{c}" puts "final: #{a.gsub(b,c)}" end 

running

>> r Enter original my text and my source: ### Enter a pattern to replace ### Enter a replacement xml.scan(/\<tag>[\s\S]*?\<\/tag\>/) a: my text and my source: ### b: ### c: xml.scan(/\<tag>[\s\S]*?\<\/tag\>/) c escaped: xml.scan(/\&lt;tag&gt;[\s\S]*?\&lt;\/tag\&gt;/) final: my text and my source: xml.scan(/###lt;tag&gt;[\s\S]*?###lt;\/tag###gt;/) => nil >> # should not be: "final: my text and my source: xml.scan(/\&lt;tag&gt;[\s\S]*?\&lt;\/tag\&gt;/)" ?? 

Updated by thiaguerd (thiago feitosa) over 6 years ago Actions #8

  • Status changed from Rejected to Open

Updated by thiaguerd (thiago feitosa) over 6 years ago Actions #9 [ruby-core:94239]

on Python 3.7.1

import html def r(): a = input('Enter original:') b = input('Enter a pattern to replace:') c = input('Enter a replacement:') print(f"a: {a}") print(f"b: {b}") print(f"c: {c}") c = html.escape(c) print(f"c escaped: {c}") print(f"final: {a.replace(b,c)}") 

running

>>> r() Enter original:my text and my source: ### Enter a pattern to replace:### Enter a replacement:xml.scan(/\<tag>[\s\S]*?\<\/tag\>/) a: my text and my source: ### b: ### c: xml.scan(/\<tag>[\s\S]*?\<\/tag\>/) c escaped: xml.scan(/\&lt;tag&gt;[\s\S]*?\&lt;\/tag\&gt;/) final: my text and my source: xml.scan(/\&lt;tag&gt;[\s\S]*?\&lt;\/tag\&gt;/) >>> # here works ... 

Updated by alanwu (Alan Wu) over 6 years ago Actions #10 [ruby-core:94241]

gsub(pattern, replacement) always interprets replacement as a regex replacement directive.
You can use the block form to substitute verbatim:

a = "test ?" b = "?" c = "\\&" a.gsub(b) { c } #=> "test \\&" 

Updated by thiaguerd (thiago feitosa) over 6 years ago Actions #11 [ruby-core:94261]

  • Tracker changed from Bug to Misc
  • ruby -v deleted (2.6.2p47 (2019-03-13 revision 67232) [x86_64-linux])
  • Backport deleted (2.5: UNKNOWN, 2.6: UNKNOWN)

alanwu (Alan Wu) wrote:

gsub(pattern, replacement) always interprets replacement as a regex replacement directive.
You can use the block form to substitute verbatim:

a = "test ?" b = "?" c = "\\&" a.gsub(b) { c } #=> "test \\&" 

Nice, tank you.

Updated by matz (Yukihiro Matsumoto) over 6 years ago Actions #12

  • Status changed from Open to Closed
Actions

Also available in: PDF Atom