Video Coming Soon...

Created by Zed A. Shaw Updated 2025-11-14 00:08:54

45: grep

The grep command is an extremely useful tool. It searches through files--even recursively--looking for patterns of text. These patterns use something called a "regular expression", or "regex" for short. A regex uses simple characters to create a matching pattern that can search for things like, "all numbers starting with 0 through 9 before a lowercase letter."

Here's a quick regex crash course:

After that you can put any text you want and those letters get matched exactly. Here's some regex to try on your own code:

The Challenge

Your grep should take a single regex and scan either a listed number of files or the os.Stdin input stream. It should also be able to process the three example regex I gave you and run on your main.go file.

The documentation for grep is:

Requirements

The only package that is mandatory for grep is the regexp package. Here's what I used:

See the list of requirements

Spoilers

Here's my quick implementation of grep to get you going. Can you do better?

See my first version codeView Source file go-coreutils/grep/main.go Only

package main

import (
  "fmt"
  "regexp"
  "os"
  "bufio"
  "flag"
  "log"
  "io"
)

func ScanInput(input io.Reader, exp string, prefix string) {
  scan := bufio.NewScanner(input)
  re, err := regexp.Compile(exp)

  if err != nil { log.Fatal(err) }

  for scan.Scan() {
    line := scan.Text()

    if re.MatchString(line) {
      if prefix != "" {
        fmt.Print(prefix, ": ")
      }

      fmt.Println(line)
    }
  }
}

func main() {
  // NOTE: can we avoid flag here since it's just raw args?
  flag.Parse()

  args := flag.Args()

  if len(args) == 0 {
    log.Fatal("USAGE: grep <regex> [files...]")
  } else if len(args) == 1 {
    ScanInput(os.Stdin, args[0], "")
  } else {
    exp := args[0]
    files := args[1:]

    for _, file := range files {
      input, err := os.Open(file)
      if err != nil { log.Fatal(err) }

      ScanInput(input, exp, file)
    }
  }
}

Testing It

If you want to push your learning further then you can try to implement an automated test for this. I actually need to learn how to test utilities like this with Go, so for now just consider this an extra challenge for later until I learn how to teach it.

Previous Lesson Next Lesson

Register for Learn Go the Hard Way

Register today for the course and get the all currently available videos and lessons, plus all future modules for no extra charge.