$ grep
is often used when parsing logs and other files containing a bunch of text. But, a blog post with snippets of random logs doesn't sound fun to read, and many developers are familiar with JavaScript. Let's practice some common grep use cases with uncommon files, a tiny JavaScript program.
If you'd like to $ grep
along, you can clone the source files from the $ grep essentials companion code repo.
Scenario
Presume we're in a predicament,
- We don't have a text editor
- We can't figure out how to use VIM
- We're eager to interrogate a few odd JavaScript files for specific text (and emojis!)
Our directory contains index.js
, trees.js
, leaves.js
, and barnYardAnimal.js
.
index.js
const { isTree } = require('./trees')
const { isLeaf } = require('./leaves')
const { isBarnYardAnimal } = require('./barnYardAnimal')
console.log(`\nIs 🌲 a tree? ${ isTree('🌲') }`) // true
console.log(`Is 🍂 a tree? ${ isTree('🍂') }`) // false
console.log(`Is 🐄 a tree? ${ isTree('🐄') }\n`) // false
console.log(`Is 🌲 a leaf? ${ isLeaf('🌲') }`) // false
console.log(`Is 🍂 a leaf? ${ isLeaf('🍂') }`) // true
console.log(`Is 🐄 a leaf? ${ isLeaf('🐄') }\n`) // false
console.log(`Is 🌲 a barn yard animal? ${ isBarnYardAnimal('🌲') }`) // false
console.log(`Is 🍂 a barn yard animal? ${ isBarnYardAnimal('🍂') }`) // false
console.log(`Is 🐄 a barn yard animal? ${ isBarnYardAnimal('🐄') }\n`) // true
trees.js
function isTree(tree) {
const trees = ["🌲", "🌳", "🌴", "🎄", "🎋"];
return trees.includes(tree);
}
module.exports = { isTree };
leaves.js
function isLeaf(leaf) {
const leaves = [ '🍁', '🍂', '🍃' ]
return leaves.includes(leaf);
}
module.exports = { isLeaf }
barnYardAnimal.js
function isBarnYardAnimal(animal) {
const barnYardAnimals = ["🐑", "🐐", "🐖", "🐄", "🐓"];
return barnYardAnimals.includes(animal);
}
module.exports = { isBarnYardAnimal };
Basic $ grep
Usage
The $ grep
utility provides a way to search files for specific text. Let's try it out!
Searching for text in a file with $ grep
Hmm, I wonder if the barnYardAnimal.js
contains a function called isBarnYardAnimal
. We can quickly determine this with $ grep
,
The command,
grep isBarnYardAnimal barnYardAnimal.js
yields two matches,
function isBarnYardAnimal(animal) {
module.exports = { isBarnYardAnimal }
In this case, we're searching for the string "isBarnYardAnimal"
in the file barnYardAnimal.js
.
Searching for emojis in a file with $ grep
$ grep
also support emoji searches! Sure, the real world use case is minimal, but it's fun -> so let's find out if we include the pig emoji 🐖 in barnYardAnimal.js
.
The command,
grep 🐖 barnYardAnimal.js
yields,
const barnYardAnimals = [ '🐑', '🐐', '🐖', '🐄', '🐓' ]
In this case, we're searching for the emoji string 🐖
in the file barnYardAnimal.js
.
Searching for text in multiple files with $ grep
Let's find out if our flora related files export any functions.
The command,
grep exports leaves.js trees.js
yields,
leaves.js:module.exports = { isLeaf }
trees.js:module.exports = { isTree }
In this case, we're searching for the string "exports"
in two files, leaves.js
and trees.js
.
Searching for text in a directory with $ grep
We can use the $ grep
command's -r
option to recursively serach subdirectories. Let's try it out to determine which of our files contains console.log
statements.
The command,
grep -r console.log .
yields,
./index.js:console.log(`\nIs 🌲 a tree? ${ isTree('🌲') }`) // true
./index.js:console.log(`Is 🍂 a tree? ${ isTree('🍂') }`) // false
./index.js:console.log(`Is 🐄 a tree? ${ isTree('🐄') }\n`) // false
./index.js:console.log(`Is 🌲 a leaf? ${ isLeaf('🌲') }`) // false
./index.js:console.log(`Is 🍂 a leaf? ${ isLeaf('🍂') }`) // true
./index.js:console.log(`Is 🐄 a leaf? ${ isLeaf('🐄') }\n`) // false
./index.js:console.log(`Is 🌲 a barn yard animal? ${ isBarnYardAnimal('🌲') }`) // false
./index.js:console.log(`Is 🍂 a barn yard animal? ${ isBarnYardAnimal('🍂') }`) // false
./index.js:console.log(`Is 🐄 a barn yard animal? ${ isBarnYardAnimal('🐄') }\n`) // true
In this case, the -r
options denotes we're recursively searching for the string "console.log"
in our current directory, denoted with .
.
Excluding files from $ grep
search
Uh oh, it looks like cloning this project from GitHub included a README.md
file. Our README.md
includes a handful of the emojis in our JavaScript files. Imagine we want to search for an emoji in our JavaScript files and not our readme. To do so, we exclude the README.md
file while searching our current directory.
The command,
grep 🌲 -r . --exclude README.md
yields,
./index.js:console.log(`\nIs 🌲 a tree? ${ isTree('🌲') }`) // true
./index.js:console.log(`Is 🌲 a leaf? ${ isLeaf('🌲') }`) // false
./index.js:console.log(`Is 🌲 a barn yard animal? ${ isBarnYardAnimal('🌲') }`) // false
./trees.js: const trees = [ '🌲', '🌳', '🌴', '🎄', '🎋' ]
In this case, we're using the previously mentioned -r
option to recursively search our current directory for the 🌲 emoji. We introduce the --exclude
option to, you guessed it, exclude the README.md
file from our search.
Finding files with a ;
Close inspection of our files reveals we're implicitly relying on JavaScript's automatic semicolon insertion (ASI). Let's find out if we've included any semicolons in our directory. To do this, we introduce the
The command,
grep -r . -e \;
yields a line containing a semicolon,
./leaves.js: return leaves.includes(leaf);
In this case, we're again using the -r
option to recursively search our current directory for a ;
character. The new -e
options allows us to search using a regular expression, \;
. Our search would otherwise fail without the -e
option.
Case insensitive searches with $ grep
By default, $ grep
is case sensitive. Let's find all occurrences of the word animal in our directory regardless of the word's case. Doing this with $ grep
is straightforward, we simply introduce the -i
option. This instructs the $ grep
command to ignore the case, performing case insensitive matching.
The command,
grep -i animals -r .
yields two matches in barnYardAnimal.js
,
./barnYardAnimal.js: const barnYardAnimals = [ '🐑', '🐐', '🐖', '🐄', '🐓' ]
./barnYardAnimal.js: return barnYardAnimals.includes(animal)
Outputting file Names with $ grep
What if we only want our $ grep
command to output file names? We can easily do this using the -l
option. Let's find all of the files that export a function in our directory.
The command,
grep exports -r . -l
yields,
./barnYardAnimal.js
./trees.js
./leaves.js
Outputing lines after a match with $ grep
Imagine we want some additional context when outputting $ grep
matches. We can do this using the -A
options. The -A
option takes a single argument, num
, which is the number of lines to output after a match.
The command,
grep function -r . -A 4
yields 4 lines after each match for the word "function"
,
$ ./barnYardAnimal.js:function isBarnYardAnimal(animal) {
$ ./barnYardAnimal.js- const barnYardAnimals = [ '🐑', '🐐', '🐖', '🐄', '🐓' ]
$ ./barnYardAnimal.js-
$ ./barnYardAnimal.js- return barnYardAnimals.includes(animal)
$ ./barnYardAnimal.js-}
--
$ ./trees.js:function isTree(tree) {
$ ./trees.js- const trees = [ '🌲', '🌳', '🌴', '🎄', '🎋' ]
$ ./trees.js-
$ ./trees.js- return trees.includes(tree)
$ ./trees.js-}
--
$ ./leaves.js:function isLeaf(leaf) {
$ ./leaves.js- const leaves = [ '🍁', '🍂', '🍃' ]
$ ./leaves.js-
$ ./leaves.js- return leaves.includes(leaf);
$ ./leaves.js-}
Wrapping Up
The above are a cursory overview of a few common $ grep
uses. The command has many more -> check them all out by running $ man grep
.