Regex back reference in gsub

D

Dan Fitzpatrick

I am converting URLs in a text file to hyperlinks with the following
regex. But the results only show up after the gsub is run a second time.

str = "A link to http://ruby-lang.org"
str.gsub(/([\s|\>|\[|\(])((ftp:\/\/|http(s?):\/\/))([\w\.\?\/&=\-~:%]+)\b/i,
"#{$1}<a href='#{$3}#{$5}#{$6}' target='_blank'>#{$5}#{$6}</a>")
#=> "A link to<a href='' target='_blank'></a>"
str.gsub(/([\s|\>|\[|\(])((ftp:\/\/|http(s?):\/\/))([\w\.\?\/&=\-~:%]+)\b/i,
"#{$1}<a href='#{$3}#{$5}#{$6}' target='_blank'>#{$5}#{$6}</a>")
#=> "A link to <a href='http://ruby-lang.org'
target='_blank'>ruby-lang.org</a>"

Is there another way to do this?
 
D

daz

Dan said:
I am converting URLs in a text file to hyperlinks with the following
regex. But the results only show up after the gsub is run a second time.

str = "A link to http://ruby-lang.org"
str.gsub(/([\s|\>|\[|\(])((ftp:\/\/|http(s?):\/\/))([\w\.\?\/&=\-~:%]+)\b/i,
"#{$1}<a href='#{$3}#{$5}#{$6}' target='_blank'>#{$5}#{$6}</a>")
#=> "A link to<a href='' target='_blank'></a>"
str.gsub(/([\s|\>|\[|\(])((ftp:\/\/|http(s?):\/\/))([\w\.\?\/&=\-~:%]+)\b/i,
"#{$1}<a href='#{$3}#{$5}#{$6}' target='_blank'>#{$5}#{$6}</a>")
#=> "A link to <a href='http://ruby-lang.org'
target='_blank'>ruby-lang.org</a>"

Is there another way to do this?

Hi,

Just a small change.

You need to use the block form of gsub, here, because the $n backrefs
are not set until the regex has completed. When using the non-block
form, you can normally use \1, \2 etc. instead of $1, $2 etc. but,
because you're using interpolation with #{...} inside your replacement
string, it gets a bit tricky doubling up the backslashes.

That's really not clear at all, sorry :)

The reason why your example took two runs, is because the first run
sets the $n backrefs exactly the way you want them for the second run.

#--------------------------------------
str = "A link to http://ruby-lang.org"

res = str.gsub(/([\s|\>|\[|\(])((ftp:\/\/|http(s?):\/\/))([\w\.\?\/&=\-~:%]+)\b/i) do
"#{$1}<a href='#{$3}#{$5}#{$6}' target='_blank'>#{$5}#{$6}</a>"
end

puts res #-> A link to <a href='http://ruby-lang.org' target='_blank'>ruby-lang.org</a>
#--------------------------------------


daz
 
D

Dan Fitzpatrick

--snip--
#--------------------------------------
str = "A link to http://ruby-lang.org"

res = str.gsub(/([\s|\>|\[|\(])((ftp:\/\/|http(s?):\/\/))([\w\.\?\/&=\-~:%]+)\b/i)
do
"#{$1}<a href='#{$3}#{$5}#{$6}' target='_blank'>#{$5}#{$6}</a>"
end

puts res #-> A link to <a href='http://ruby-lang.org'
target='_blank'>ruby-lang.org said:
#--------------------------------------

daz,

Thanks for the explanation. That works great.

Dan
 
D

David A. Black

Hi --

Dan said:
I am converting URLs in a text file to hyperlinks with the following
regex. But the results only show up after the gsub is run a second time.

str = "A link to http://ruby-lang.org"
str.gsub(/([\s|\>|\[|\(])((ftp:\/\/|http(s?):\/\/))([\w\.\?\/&=\-~:%]+)\b/i,
"#{$1}<a href='#{$3}#{$5}#{$6}' target='_blank'>#{$5}#{$6}</a>")
#=> "A link to<a href='' target='_blank'></a>"
str.gsub(/([\s|\>|\[|\(])((ftp:\/\/|http(s?):\/\/))([\w\.\?\/&=\-~:%]+)\b/i,
"#{$1}<a href='#{$3}#{$5}#{$6}' target='_blank'>#{$5}#{$6}</a>")
#=> "A link to <a href='http://ruby-lang.org'
target='_blank'>ruby-lang.org</a>"

Is there another way to do this?

Hi,

Just a small change.

You need to use the block form of gsub, here, because the $n backrefs
are not set until the regex has completed. When using the non-block
form, you can normally use \1, \2 etc. instead of $1, $2 etc. but,
because you're using interpolation with #{...} inside your replacement
string, it gets a bit tricky doubling up the backslashes.

The #{...} usage isn't actually necessary, though. You could do:

'\1<a href=\'\3\5\6\' target=\'_blank\'>\5\6</a>'

or

%q{\1<a href='\3\5\6' target='_blank'>\5\6</a>')}

(to avoid the '-escaping).


David
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top