0

I'm writing a program to parse a basic text file, and compare certain lines from it to results from a test. I'm using specific words to find the line which should be compared to the result from the test, and then passing or failing the result based upon whether or not the line matches the result (they should be exactly the same). I'm using the following general format:

File.open(file).each do |line|
  if line include? "Revision"
    if line==result
     puts "Correct"
    else
     puts "Fail"

Most of the cases are just one line, so that's easy enough. But for a few of the cases, my result is 4 lines long, not just one. So, once I find the line I need, I need to check to see if the result is equal to the line of interest plus the following 3 lines after it. This is how the information is formatted in the file being read, and also how the result from the test should look:

Product Serial Number: 12058-2865
Product Part Number: 3456
Product Type: H-Type
Product Version: 2.07

Once the line of interest is found, I just need to compare the line of interest plus the next three lines to the whole result.

if line include? "Product Serial Number"
  #if (#this line and the next 3) == result
   puts Correct
  else
   puts "Fail"

How do I do this?

pjano1
  • 143
  • 1
  • 3
  • 10

3 Answers3

0
text =<<_
My, oh my
Product Serial Number: 12058-2865
Product Part Number: 3456
Product Type: H-Type
Product Version: 2.07
My, oh my
Product Serial Number: 12058-2865
Product Part Number: 3456
Product Type: H-Type
Product Version: 2.08
My, ho my
Product Serial Number: 12058-2865
Product Part Number: 3456
Product Type: H-Type
Product Version: 2.07
_

result =<<_.lines
Product Serial Number: 12058-2865
Product Part Number: 3456
Product Type: H-Type
Product Version: 2.07
_
#=> ["Product Serial Number: 12058-2865\n", "Product Part Number: 3456\n",
#    "Product Type: H-Type\n", "Product Version: 2.07\n"]

FName = "test"
File.write(FName, text)
  #=> 339
target = "Product Serial Number"

nbr_result_lines = result.size
  #=> 4
lines = File.readlines(FName)
  #=> ["My, oh my\n",
  #    "Product Serial Number: 12058-2865\n",
  #    ...
  #    "Product Version: 2.07\n"]
lines.each_with_index do |line, i|
  (puts (lines[i, nbr_result_lines] == result ? "Correct" : "Fail")) if 
  line.match?(target)
end
  # "Correct"
  # "Fail"
  # "Correct"

Note that the array lines[i, nbr_result_lines] will end with one or more nils when i is sufficiently large.

If the file is so large that slurping it into an array is undesirable or infeasible, one could

  • read the first nbr_result_lines into a buffer (using, say, IO::foreach);
  • compare target with the first line of the buffer, if a match, compare result with the buffer;
  • remove the first line of the buffer, add the next line of the file to the end of the buffer and repeat the above, continuing until the buffer has been examined after the last line of the file has been added to it.
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100
  • 1
    @SergioTulentsev, thanks, I'll have a look at the link. I added some text to my answer to describe one way to avoid slurping the file. – Cary Swoveland Oct 16 '18 at 17:31
0

Well you can have several approaches for this, the easy way is to go through each line. and try to detect the sequence like this, it should be something similar to state machine for detecting a sequence:

step = 0
File.open('sample-file.txt').each do |line|
  if /^Product Serial Number.*/.match? line
    puts(step = 1)
  elsif /^Product Part Number.*/.match?(line)  && step == 1
    puts(step = 2)
  elsif /^Product Type.*/.match?(line) && step == 2
    puts(step = 3)
  elsif /^Product Version.*/.match?(line) && step == 3
    puts 'correct'
    puts(step = 0)
  else
    puts(step = 0)
  end
end

with this result:

ruby read_file.rb
1
2
3
correct
0
0
1
0
0
0
0
0
0
1
2
3
correct
0
0

and this sample file:

Product Serial Number: 12058-2865
Product Part Number: 3456
Product Type: H-Type
Product Version: 2.07
no good line
Product Serial Number: 12058-2865
BAD Part Number: 3456
Product Type: H-Type
Product Version: 2.07
no good line
no good line
no good line
Product Serial Number: 12058-2865
Product Part Number: 3456
Product Type: H-Type
Product Version: 2.07
no good line
anquegi
  • 11,125
  • 4
  • 51
  • 67
0

There is exist similar answered question: reading a mulitply lines at once

I think if you have file with knowed format and have persisten series of lines, you can read multiply lines to array and iterate over array elements with needed logic.

File.foreach("large_file").each_slice(8) do |eight_lines| # eight_lines is an array containing 8 lines. # at this point you can iterate over these lines end

Yep loop in loop not very good, but better rather multiply if else

Ivan Gurzhiy
  • 229
  • 2
  • 6