开发者

Ruby Regex not matching

I'm writing a short class to extract email addresses from documents. Here is my code so far:

# Class to scrape documents for email addresses

class EmailScraper

  EmailRegex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

  def EmailScraper.scrape(doc)
    email_addresses = []
    File.open(doc) do |file|
      while line = file.gets
        temp = line.scan(EmailRegex)

        temp.each do |email_address|
          puts email_address
          emails_addresses << email_address
        end

      end
    end 
    return email_addresses
  end
end


if EmailScraper.scrape("email_tests.txt").empty?
  puts "Empty array"
else
  puts EmailScraper.scrape("email_tests.txt")
end

My "email_tests.txt" file looks like so:

example@live.com
another_example90@hotmail.com
example3@diginet.ie

When I run this script, all I get is the "Empty array" printout. However, when I fire u开发者_运维问答p irb and type in the regex above, strings of email addresses match it, and the String.scan function returns an array of all the email addresses in each string. Why is this working in irb and not in my script?


Several things (some already mentioned and expanded upon below):

  • \z matches to the end of the string, which with IO#gets will typically include a \n character. \Z (upper case 'z') matches the end of the string unless the string ends with a \n, in which case it matches just before.
  • the typo of emails_addresses
  • using \A and \Z is fine while the entire line is or is not an email address. You say you're seeking to extract addresses from documents, however, so I'd consider using \b at each end to extract emails delimited by word boundaries.
  • you could use File.foreach()... rather than the clumsy-looking File.open...while...gets thing
  • I'm not convinced by the Regex - there's a substantial body of work already around:

There's a smarter one here: http://www.regular-expressions.info/email.html (clicking on that odd little in-line icon takes you to a piece-by-piece explanation). It's worth reading the discussion, which points out several potential pitfalls.

Even more mind-bogglingly complex ones may be found here.

class EmailScraper

  EmailRegex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\Z/i # changed \z to \Z

  def EmailScraper.scrape(doc)

    email_addresses = []

    File.foreach(doc) do |line| # less code, same effect
      temp = line.scan(EmailRegex)
      temp.each do |email_address|
        email_addresses << email_address
      end
    end         
    email_addresses # "return" isn't needed
  end
end

result = EmailScraper.scrape("email_tests.txt") # store it so we don't print them twice if successful
if result.empty?
  puts "Empty array"
else
  puts result
end


Looks like you're putting the results into emails_addresses, but are returning email_addresses. This would mean that you're always returning the empty array you defined for email_addresses, making the "Empty array" response correct.


You have a typo, try with:

class EmailScraper

  EmailRegex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

  def EmailScraper.scrape(doc)
    email_addresses = []
    File.open(doc) do |file|
      while line = file.gets
        temp = line.scan(EmailRegex)

        temp.each do |email_address|
          puts email_address
          email_addresses << email_address
        end

      end
    end 
    return email_addresses
  end
end


if EmailScraper.scrape("email_tests.txt").empty?
  puts "Empty array"
else
  puts EmailScraper.scrape("email_tests.txt")

end


You used at the end \z try to use \Z according to http://www.regular-expressions.info/ruby.html it has to be a uppercase Z to match the end of the string.

Otherwise try to use ^ and $ (matching the start and the end of a row) this worked for me here on Regexr


When you read the file, the end of line is making the regex fail. In irb, there probably is no end of line. If that is the case, chomp the lines first.

regex=/\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
line_from_irb = "example@live.com"
line_from_file = line_from_irb +"/n"

p line_from_irb.scan(regex) # => ["example@live.com"]
p line_from_file.scan(regex) # => []
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜