Extracting an IP address from a hosts file by hostname
You can probably get by with this:

ip = File.read(hostfile).match(/^\s*([\d\.]+)\s+\b#{hostname}\s*$/)[1]


A more "complete" way might be to do:

hosts = File.foreach(hostfile)
  .grep(/^\s*([\d\.:]+)/)
  .map { |line| line.strip.split(/\s+/).reverse }
  .to_h


Which gives you a { hostname =&gt; IP } hash for everything in the file (IPv6 included for good measure). I.e. you'd just do

ip_address = hosts[hostname]


to get the IP address.

For your current code:


  It seems a little ugly and long


It is a long line, but you can always break it up. You can chain off of the end keyword just as well as off of a }, so something like this would help readability:

File.foreach(hostfile).grep(/\b#{hostname}\b/) do |m|
  /^([0-9\.]*)\b.*/.match(m)[1]
end.first


In the 2nd approach above, I could've used grep to both match and map the lines, but I thought it nicer to separate the two.


  It also seems strange to me that I need to add .first on the end in order to get the IP address string out of the array returned by grep


grep is being called for each line, meaning it'll produce an array of matching lines. Hence why you need first. You're basically filtering and mapping every line in the file. After filtering there's (presumably!) only one line left, but it'll still be in an array.

You could use detect if you're only interested in the first matching line:

line = File.foreach(hostfile).detect { |line| line =~ %r[\b#{hostname}\b] }


That'll give you only the line containing the hostname you're looking for (or nil), which you can then parse further.