Reputation: 303
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
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
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
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