Class: Grepper

Inherits:
Object
  • Object
show all
Defined in:
lib/grepper.rb,
lib/grepper/formatter.rb

Overview

Grepper – simple way to grep through files and save results

Description

The Grepper class greps through files, and returns a result set of Grepper::Result objects. Each Result object represents the matches found in a single file. The Result contains a set of Grepper::Match objects. Each Match object represents a line (the line that matched) and before- and after-context arrays. If no before or after lines were requested, those context values will be nil.

To use, you prepare a Grepper object; call run on it; and walk through the result set. This distribution comes with the Grepper::Formatter class, which is built on top of Grepper and provides fairly canonical-looking output by walking through Grepper objects. (See lib/formatter.rb.) Meanwhile, here are the details.

Preparing a Grepper object

You instantiate Grepper, and provide it with:

  • a pattern, in the form of a regular expression

  • zero or more options, as an array

  • an array of filenames

Setting the grepper’s pattern

To specify a pattern for the Grepper object:

grepper.pattern = /abc/

Setting the grepper’s file list

grepper.files = ["file1.txt", "file2.txt"]
grepper.files = Dir["grep_me/*.txt"]

Options

To set options, you provide an array of strings. For example, for a reverse grep with two lines of after-context you would do:

grepper.options = %w{ v A2 }

Available options are:

  • o – store only the part of the line that matched the pattern

  • v – negate the sense of the match

  • w – count only complete-word matches

  • An – provide n lines of after-context

  • Bn – provide b lines of before-context

Generating the result set

To generate the result set, you call run.

grepper.run

Now you can access grepper.results, and walk through all the matches.

Walking through the result set and match set

Given a Grepper object grepper, the result set will be at grepper.results. It will iterate per entry, yielding the filename and the corresponding set of matches.

grepper.results.each do |filename, matches|
  ...
end

For each match set, you can iterate like this:

matches.each do |lineno, before, line, after|
  ...
end

If you want to walk through either set and just get the objects, not broken out into their properties, you can do:

grepper.results.each_result do |result|

and

matches.each_match do |match|

Version

0.9.3, January 13, 2009

Author

David A. Black ([email protected])

Copyright and license

Copyright © 2008-2009, Ruby Power and Light, LLC

Released under the Ruby license. No warranty of any kind. Use entirely at your own risk.

Defined Under Namespace

Modules: MatchesExtension, ResultsExtension Classes: Formatter, Match, Result

Constant Summary collapse

VERSION =
'0.9.3'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeGrepper

Returns a new instance of Grepper.



109
110
111
112
113
114
# File 'lib/grepper.rb', line 109

def initialize
  @files = []
  @options = []
  @results = [].extend(ResultsExtension)
  @negate = false
end

Instance Attribute Details

#filesObject

Returns the value of attribute files.



106
107
108
# File 'lib/grepper.rb', line 106

def files
  @files
end

#optionsObject

Returns the value of attribute options.



106
107
108
# File 'lib/grepper.rb', line 106

def options
  @options
end

#patternObject

Returns the value of attribute pattern.



106
107
108
# File 'lib/grepper.rb', line 106

def pattern
  @pattern
end

#resultsObject (readonly)

Returns the value of attribute results.



107
108
109
# File 'lib/grepper.rb', line 107

def results
  @results
end

Instance Method Details

#runObject

Generate the result set.



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/grepper.rb', line 162

def run
  massage_pattern
  @negate = true if options.include?('v')
  
  after_count = $1.to_i if options.find {|o| /A(\d+)/.match(o) }
  before_count = $1.to_i if options.find {|o| /B(\d+)/.match(o) }
  if options.find {|o| /C(\d+)/.match(o) }
    after_count ||= $1.to_i
    before_count ||= $1.to_i
  end

  files.each do |file|
    result = Result.new(file)
    results << result
    buffer = []
    File.open(file) do |fh|
      i = 0
      while line = fh.gets
        i += 1
        
        if matched = match_for(line)
          match = Match.new(matched)
          match.lineno = i

          if after_count
            match.after = get_after_context(fh, after_count)
            i += (match.after || []).size
          end

          if before_count
            match.before = buffer.empty? ? nil : buffer
            buffer = []
          end

          result.matches << match

        else
          if before_count
            buffer << line
            buffer.shift if buffer.size > before_count
          end
        end
      end
    end
  end
end