Misc #16091
closedgsub
Description
a = "test ?"
b = "?"
c = "\\&"
a.gsub(b,c)
Updated by thiaguerd (thiago feitosa) over 4 years ago
- Subject changed from sub to gsub
Updated by nobu (Nobuyoshi Nakada) over 4 years ago
- Description updated (diff)
- Status changed from Open to Feedback
Updated by shyouhei (Shyouhei Urabe) over 4 years ago
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 4 years ago
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 4 years ago
@thiaguerd (thiago feitosa) 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 4 years ago
- 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 4 years ago
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(/\<tag>[\s\S]*?\<\/tag\>/)
final: my text and my source: xml.scan(/###lt;tag>[\s\S]*?###lt;\/tag###gt;/)
=> nil
>>
# should not be: "final: my text and my source: xml.scan(/\<tag>[\s\S]*?\<\/tag\>/)" ??
Updated by thiaguerd (thiago feitosa) over 4 years ago
- Status changed from Rejected to Open
Updated by thiaguerd (thiago feitosa) over 4 years ago
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(/\<tag>[\s\S]*?\<\/tag\>/)
final: my text and my source: xml.scan(/\<tag>[\s\S]*?\<\/tag\>/)
>>>
# here works ...
Updated by alanwu (Alan Wu) over 4 years ago
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 4 years ago
- 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 interpretsreplacement
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 4 years ago
- Status changed from Open to Closed