Reputation: 27
I am given a text file containing hundreds of line of information, and am tasked with pulling lines with a specific strings out. The issue is that after the line with the string being searched for is found, I also need to pull the 7 lines above it as-well.
I know this solution works for pulling specific line number. However I don't know what line number needs to be pulled, just the string on the line, along with 7 lines above the line, with the string I need.
file = File.open "file.txt"
n.times{ file.gets }
p $_
file.close
Upvotes: 1
Views: 84
Reputation: 1506
I know this is supposed to be a Ruby question, but sometimes other tools make it easier to get the results.
Did you know about grep? :
$ cat long_file.txt
line 1
line 2
line 3
line 4
line 5
line 6
line 7
line 8
line 9
line 10
target
line 11
line 12
line 13
line 14
$ grep -B 7 target long_file.txt
line 4
line 5
line 6
line 7
line 8
line 9
line 10
target
Upvotes: 0
Reputation: 110755
Let target?
be a method that takes a line from the file as an argument and returns true
or false
, depending upon whether the lines meets the matching criterion.
Code
def doit(fname)
arr = []
File.foreach(fname).with_object([]) do |line, a|
arr.shift if arr.size == 8
arr << line
if target?(line) && arr.size == 8
a << arr
arr = []
end
end
end
Example
Let's create a test file.
TARGET_LINES = ["Mary had a little lamb", "whose fleece was", "white as snow"]
a = (1..28).map { |i| "line #{i}" }
b = [*a[0,7], TARGET_LINES[1],
*a[8,10], TARGET_LINES[2],
*a[18,9], TARGET_LINES[0],
a[27]]
FName = 'test'
File.write(FName, b.join("\n"))
#=> 261
See what we have (skipping some lines).
puts File.read(FName)
line 1
line 2
...
line 7
whose fleece was
line 9
line 10
...
line 18
white as snow
line 19
line 20
...
line 27
Mary had a little lamb
line 28
Now create a target?
method:
def target?(line)
TARGET_LINES.include?(line.chomp)
end
and execute doit
:
puts doit(FName)
line 1
line 2
...
line 7
whose fleece was
line 12
line 13
...
line 18
white as snow
line 21
line 22
...
line 27
Mary had a little lamb
See the docs IO::foreach and Enumerator#with_object and Array#rotate. Note that IO
class methods such as foreach
are often invoked with the receiver File
. This is permitted because File
is a subclass of IO
. (File < IO #=> true
).
Upvotes: 1