1

I have html contents in following text.

    "This is my text to be parsed which contains url 
    http://someurl.com?param1=foo&params2=bar 
 <a href="http://thisshouldnotbetampered.com">
    some text and a url http://someotherurl.com test 1q2w
 </a> <img src="http://someasseturl.com/abc.jpeg"/>
    <span>i have a link too http://someurlinsidespan.com?xyz=abc </span> 
    "

Need a regex that will convert plain urls to hyperlink(without tampering existing hyperlink)

Expected result:

    "This is my text to be parsed which contains url 
    <a href="http://someurl.com?param1=foo&params2=bar">
http://someurl.com?param1=foo&params2=bar</a> 
 <a href="http://thisshouldnotbetampered.com">
    some text and a url http://someotherurl.com test 
1q2w </a> <img src="http://someasseturl.com/abc.jpeg"/>
    <span>i have a link too <a href="http://someurlinsidespan.com?xyz=abc">http://someurlinsidespan.com?xyz=abc</a> </span> "
krunal shah
  • 16,089
  • 25
  • 97
  • 143
  • Regular expressions are probably not the right tool for this job. Consider alternatives: http://nokogiri.org/ – Ant P Jun 11 '13 at 07:01
  • I don't know about Ruby's implementation of regexs but that works fine in www.regex101.com. And regexs are fine as long as you know the structure of your likely inputs. – ydaetskcoR Jun 11 '13 at 07:29

4 Answers4

3

Disclaimer: You shouldn't use regex for this task, use an html parser. This is a POC to demonstrate that it's possible if you expect a good formatted HTML (which you won't have anyway).

So here's what I came up with:
(https?:\/\/(?:w{1,3}.)?[^\s]*?(?:\.[a-z]+)+)(?![^<]*?(?:<\/\w+>|\/?>))

What does this mean ?

  • ( : group 1
  • https? : match http or https
  • \/\/ : match //
  • (?:w{1,3}.)? : match optionally w., ww. or www.
  • [^\s]*? : match anything except whitespace zero or more times ungreedy
  • (?:\.[a-z]+)+) : match a dot followed by [a-z] character(s), repeat this one or more times
  • (?! : negative lookahead
    • [^<]*? : match anything except < zero or more times ungreedy
    • (?:<\/\w+>|\/?>) : match a closing tag or /> or >
    • ) : end of lookahead
  • ) : end of group 1


                           regex101 online demo                                            rubular online demo

HamZa
  • 14,671
  • 11
  • 54
  • 75
  • Ok. My bad. The answers works but not for the real scenario So let me put it straight. I want to make all the url in the text a hyperlink. (The regex should not tampered existing hyperlinks). Also the above regexp does not capture the url parameter. – krunal shah Jun 11 '13 at 09:47
  • @krunalshah I tend to provide an answer to the existing question. You didn't mention anywhere you wanted to match url parameters, not even in your examples. So what does not work in your real scenario ? – HamZa Jun 11 '13 at 09:51
2

Maybe you could do a search-and-replace first to remove the HTML elements. I don't know Ruby, but the regex would be something like /<(\w+).*?>.*?</\1>/. But it might be tricky if you have nested elements of the same type.

David Knipe
  • 3,417
  • 1
  • 19
  • 19
  • +1 for remove tags, but that expression could be better if you want to do it with regex. For example it wouldn't remove image tags, or it would remove whole paragraphs (`

    i want http://this.url

    `). I'd suggest something simple like `?\w+[^>]*>`.
    – Qtax Jun 11 '13 at 07:54
  • I disagree with your interpretation of the question, but it's a moot point as the question has now changed. – David Knipe Jun 11 '13 at 18:39
0

Maybe try http://rubular.com/ .. there are some Regex tips helps you get the desired output.

tokhi
  • 21,044
  • 23
  • 95
  • 105
0

I would do something like this:

require 'nokogiri'

doc = Nokogiri::HTML.fragment <<EOF
This is my text to be parsed which contains url 
http://someurl.com  <a href="http://thisshouldnotbetampered.com">
some text and a url http://someotherurl.com test 1q2w </a> <img src="http://someasseturl.com/abc.jpeg"/>
EOF

doc.search('*').each{|n| n.replace "\n"}

URI.extract doc.text
#=> ["http://someurl.com"]
pguardiario
  • 53,827
  • 19
  • 119
  • 159