Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extract names from File using Ruby and Grep

Tags:

grep

ruby

I have a file with the following data:

other data
user1=name1
user2=name2
user3=name3
other data

to extract the names I do the following

names = File.open('resource.cfg', 'r') do |f|
  f.grep(/[a-z][a-z][0-9]/)
end

which returns the following array

user1=name1
user2=name2
user3=name3

but I really want only the name part

name1
name2
name3

Right now I'm doing this after the file step:

names = names.map do |name|
  name[7..9]
end

is there a better way to do? with the file step


2 Answers

You could do it like this, using String#scan with a regex:

Code

File.read(FNAME).scan(/(?<==)[A-Za-z]+\d+$/)

Explanation

Let's start by constructing a file:

FNAME = "my_file"

lines =<<_
other data
user1=name1
user2=name2
user3=name3
other data
_

File.write(FNAME,lines)

We can confirm the file contents:

puts File.read(FNAME)
other data
user1=name1
user2=name2
user3=name3
other data

Now run the code::

File.read(FNAME).scan(/(?<==)[A-Za-z]+\d+$/)
  #=> ["name1", "name2", "name3"]

A word about the regex I used.

(?<=...)

is called a "positive lookbehind". Whatever is inserted in place of the dots must immediately precede the match, but is not part of the match (and for that reason is sometimes referred to as as "zero-length" group). We want the match to follow an equals sign, so the "positive lookbehind" is as follows:

(?<==)

This is followed by one or more letters, then one or more digits, then an end-of-line, which comprise the pattern to be matched. You could of course change this if you have different requirements, such as names being lowercase or beginning with a capital letter, a specified number of digits, and so on.

like image 81
Cary Swoveland Avatar answered May 08 '26 12:05

Cary Swoveland


Is your code working as you have posted it?

names = File.open('resource.cfg', 'r') { |f| f.grep(/[a-z][a-z][0-9]/) }
names = names.map { |name| name[7..9] }
=> ["ame", "ame", "ame"]

You could make it into a neat little one-liner by writing it as such:

names = File.readlines('resource.cfg').grep(/=(\w*)/) { |x| x.split('=')[1].chomp }
like image 21
Zajn Avatar answered May 08 '26 14:05

Zajn



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!