Reputation: 352
I have files that have a bunch of lines containing text and numbers. The text in each file stays the same, but the numbers change. (This is running data, so the lines are things like "- Active Duration 28:19, - Total distance 3.66mi.", etc.)
What I want to do is locate the individual numbers in these lines, then create my own output, such as: "Ran #{distance} in #{time}"
I'm able to locate these numbers in the lines using regular expressions, but I cannot figure out how to then take those values and make them into their own strings. I'm not even sure regex is the right approach. I've been running things like this:
if line =~/\d*\.\d*/
found completed = true
But then I'm not sure what comes next.
I hope I'm being clear—and thanks in advance for your help.
Upvotes: 1
Views: 110
Reputation: 103
Updated answer to show iteration over file.
I put the results into a hash so that key-value pairs could be utilised for the manipulation of the data. New keys could be added for the unit of measurement, etc.
runData_20130620.txt
-Active Duration 09.87, -Total Distance 100.0m
-Active Duration 15:19, -Total Distance 4.98km
-Active Duration 03:00, -Total Distance 1.0mile
-Active Duration 21:14, -Total Distance 3.68, -Sweat Produced 5.99Gallons
-Active Duration 22:31, -Total Distance 3.65mi
Code
File.foreach("runData_20130620.txt") do |line|
# Create hash, parsing string with regex pattern
runData = Hash[*line.scan(/([^, \-]\D*) (\d*[.:]\d*)/).to_a.flatten]
# This will convert the string keys to symbols, replacing white-space with
# underscores and downcasing
runData = Hash[runData.map { |k,v|
[k.gsub(/\s+/, "_").downcase.to_sym, v] }]
# display results
#runData.each { |k,v| puts "#{k} ** #{v}" }
# display using hash symbol access...
puts "\nRan a distance of #{ runData[:total_distance]} in
runData[:active_duration]} "
puts "Man, I am unfit!" if runData[:sweat_produced]
end
Results
Ran a distance of 100.0 in 09.87
Ran a distance of 4.98 in 15:19
Ran a distance of 1.0 in 03:00
Ran a distance of 3.68 in 21:14
Man, I am unfit!Ran a distance of 3.65 in 22:31
Upvotes: 1
Reputation: 126
You can use regex in the element reference to get the number data. For example:
2.0.0-p0 :010 > distance = line[/\d*\.\d*/]
=> "3.66"
2.0.0-p0 :011 > time = line[/\d*:\d*/]
=> "28:19"
2.0.0-p0 :012 > puts "Ran #{distance} in #{time}"
Ran 3.66 in 28:19
=> nil
Upvotes: 2
Reputation: 89639
You can do that:
rawlines = <<EOF
- Active Duration 28:19, - Total distance 3.66mi.
- Active Duration 25:12, - Total distance 3.66mi.
- Active Duration 24:10, - Total distance 3.66mi.
- Active Duration 28:21, - Total distance 3.66mi.
- Active Duration 27:19, - Total distance 3.66mi.
EOF
rawlines.scan(/Active Duration (\d++:\d++), - Total distance (\d++(?>\.\d++)?)/) do |dur, dist|
puts "Ran #{dist} in #{dur}\n"
end
Upvotes: 1