user3927287
user3927287

Reputation: 303

Ruby include? on each.line.any?

I am looking to search for multiple strings from each line of a log file

     if
        File.open('filename.log').each_line.any?{|line| ["ERROR:", "***Error",].include?(line) }
        puts 'Pass'
        else
        puts 'Fail'
     end
     gets

The program keeps outputting Fail, but the log file does contain 'ERROR:' on one line and '***Error' on another line

I'm new to Ruby so any help would be greatly appreciated

After reviewing your helpful answers, I think my initial question is incorrect and misleading. My apologies.

I was looking to verify that a log file contains multiple sentences.

rb file
["All times are valid", "Export complete"]

Log File contents
[Time Stamp] [file_name] All times are valid
[Time Stamp] [file_name] Export complete

Results in Pass

Log File contents
[Time Stamp] [file_name] All times are valid
[Time Stamp] [file_name] Export failed

Results in Fail

Is there something other than .any? I could use?

Thanks

Upvotes: 0

Views: 625

Answers (3)

Justin Ko
Justin Ko

Reputation: 46836

Given that you want to check that each phrase appears at least in the log, you can use a combination of all? and any?. Basically use all? to iterate through the required phrases and any? to check each line for the phrase.

required = ["All times are valid", "Export complete"]
log = File.open('filename.log')
result = required.all? do |phrase|
    log.any? { |line| line.include?(phrase) }
end
puts result ? 'Pass' : 'Fail'

If you are searching for many phrases in a large log, you might find this slow since it will need to make multiple passes of the same line. You could change it around to check each line just once:

required = ["All times are valid", "Export complete"]
log.each do |line|
    required.delete_if { |phrase| line.include?(phrase) }
    break if required.empty?
end
puts required.empty? ? 'Pass' : 'Fail'

Upvotes: 2

Cary Swoveland
Cary Swoveland

Reputation: 110685

@Justin has explained why you are having the problem. I wasn't sure if you were searching for words or substrings. If the former, "NOERROR:" would not match; if the latter, it would. Justin assumed the former. If it's words you're looking for, one way to do that is to use array intersection:

error_words = ["ERROR:", "***Error"]
line1 = "Is there an ERROR: here?"
line2 = "Is there a NOERROR: here?"

def check_it(line, error_words)
  puts ((line.split(/\s+/) & error_words).any?) ?  "fail" : "pass" 
end

check_it(line1, error_words) #=> "fail"
check_it(line2, error_words) #=> "pass"

Upvotes: 0

max
max

Reputation: 102055

You could also use a regular expression to test for error lines if you want to be a bit more picky:

class LogFile
    def initialize(fn)
        @lines = IO.readlines(fn)
    end
    def errors?
        @lines.any? do |line|
            !/^ERROR\:/.match(line).nil?
        end
    end 
end

require 'test/unit'
class TestLogFile < Test::Unit::TestCase

    def testErrors
        log = LogFile.new('filewitherrors.log')
        assert(log.errors?)
    end

    def testErrorsWithCleanFile
        log = LogFile.new('okfile.log')
        assert(!log.errors?)
    end
end

Upvotes: 0

Related Questions