timmy24565
timmy24565

Reputation: 27

Ruby pattern matching and printing the wrong line

I am new to Ruby and working on how to read text files and check if the pattern matches or not. I am not not sure how to print the wrong lines.

For example, this is the text file:

id: 1   food: apple, banana
id: 2   food: orange
ids: 3   food: apple, banana
id: 4   food: hello, yellow
id: 5food: apple, banana

Reading the file

File.open(ARGV[0]) do |f1|  
while line = f1.gets  
pattern = /id[:] [[:digit:]]+ food[:] [a-z,]+/
puts line.scan(pattern)
end 

This prints the following results

id: 1   food: apple, banana
id: 2   food: orange
id: 4   food: hello, yellow

But I want to print the wrong lines

ids: 3   food: apple, banana
id: 5food: apple, banana

I am not sure how do check if the pattern doesn't match then print the lines that are formatted incorrectly.

Upvotes: 0

Views: 230

Answers (2)

Cary Swoveland
Cary Swoveland

Reputation: 110685

Suppose the file is read into the variable contents:

contents =<<_
id: 1   food: apple, banana
id: 2   food: orange
ids: 3   food: apple, banana
id: 4   food: hello, yellow
id: 5food: apple, banana
_

If food: is required, you could use the following regular expression.

r = /
    \A                   # match beginning of string
    id:\s+               # match "id:" followed by > 0 spaces
    \d+\s+               # match > 0 digits followed by > 0 spaces
    food:\s+             # match "food:" followed by > 0 spaces
    [[:alpha:]]+         # match > 0 (uppercase or lowercase) letters  
    (?:,\s+[[:alpha:]]+) # match a comma, > 0 spaces, > 0 letters in a non-capture group
    *                    # match > 0 instances of the aforementioned non-capture group
    \n                   # match newline      
    \z                   # match end of string
    /x                   # free-spacing regex definition mode

contents.each_line { |line| puts line if line !~ r }

prints

ids: 3   food: apple, banana
id: 5food: apple, banana

Upvotes: 1

Ursus
Ursus

Reputation: 30056

scan returns an empty array if there are no matches. So you could do

File.open(ARGV[0]) do |f1|  
  while line = f1.gets  
    pattern = /id[:] [[:digit:]]+ synset[:] [a-z,]+/
    puts line if line.scan(pattern).empty?
  end
end 

Another way, cleaner. You can use =~ method to see if a line match a pattern. And it returns the matching index if the pattern match or nil, if none matches.

File.open(ARGV[0]) do |f1|  
  while line = f1.gets  
    pattern = /id[:] [[:digit:]]+ synset[:] [a-z,]+/
    puts line unless line =~ pattern
  end
end 

Upvotes: 1

Related Questions