liveBook · Manning

Grep

As explained in The Well-Grounded Rubyist, Fourth Edition

grep is a Ruby Enumerable method that selects elements whose case-equality comparison with a supplied argument is true and can optionally transform the selected elements with a block.

Ruby’s Enumerable#grep selects elements for which the supplied expression returns true when applied with case equality (===). Its familiar use is filtering strings with a regular expression, but the same mechanism supports classes, ranges, and other objects. section 10.3.3 section 11.7.4

>> colors = %w(red orange yellow green blue indigo violet)
=> ["red", "orange", "yellow", "green", "blue", "indigo", "violet"]
>> colors.grep(/o/)
=> ["orange", "yellow", "indigo", "violet"]

A regular expression selects the colors containing the letter o. section 10.3.3

Conceptually, enumerable.grep(expression) behaves like enumerable.select { |element| expression === element }. The expression controls the meaning of matching: String selects strings, while 50..100 selects numbers included in that range. section 10.3.3

>> miscellany = [75, "hello", 10...20, "goodbye"]
=> [75, "hello", 10...20, "goodbye"]
>> miscellany.grep(String)              1
=> ["hello", "goodbye"]                 1
>> miscellany.grep(50..100)     2
=> [75]                         2

The same grep call uses String as a type test and a Range as an inclusion test. section 10.3.3

Regular expressions make grep concise, but their matching remains type-specific:

  • grep(/pattern/) selects only elements for which the regular expression’s === match succeeds. section 11.7.4
  • Numbers are not automatically converted to strings, so [1, 2, 3].grep(/1/) returns an empty array. section 11.7.4
  • grep(expression) { |item| ... } filters first, then yields each selected item and collects the block’s return values. section 10.3.3 section 11.7.4
>> colors = %w(red orange yellow green blue indigo violet)
=> ["red", "orange", "yellow", "green", "blue", "indigo", "violet"]
>> colors.grep(/o/) {|color| color.capitalize }
=> ["Orange", "Yellow", "Indigo", "Violet"]

A block transforms each selected color, combining filtering with mapping in one call. section 10.3.3

Filtering introspection results

Because symbols exhibit string-like behavior for grep, an object’s method list can be searched with a regular expression: string.methods.grep(/case/).sort returns method names involving case. A pattern such as /.!/ finds names ending in a bang rather than merely containing !. section 15.2.1

grep is therefore a compact selection tool whose behavior comes from the argument’s implementation of ===. Use it when the matching expression already captures the predicate; use select when the condition needs an ordinary block. section 10.3.3 section 11.7.4

How The Well-Grounded Rubyist, Fourth Edition covers it

How deep it goes
Explains matching mechanics, block transformation, type behavior, and contrasts grep with select without detailing Enumerable internals.
Examples
Uses color matching, mixed String and Range selection, capitalization, regexp country filtering, and method-list searches.
What it assumes
Assumes familiarity with Enumerable iteration, regular expressions, blocks, and the case-equality operator.
What you can do after
Apply it via Enumerable#grep to filter collections and optionally transform matching elements in the same operation.
How it connects
Connects Enumerable, case equality, regular expressions, select, map, ranges, classes, symbols, and runtime introspection.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of The Well-Grounded Rubyist, Fourth Edition. The section links point to the parts of the book it draws on.