An I/O Project Building a Small Grep
This chapter is both a recap of the many skills you've learned so far and an exploration of a few more standard library features. We're going to build a command-line tool that interacts with file and command line input/output to practice some of the Rust you now have under your belt.
Rust's speed, safety, 'single binary' output, and cross-platform support make
it a good language for creating command line tools, so for our project we'll
make our own version of the classic command line tool grep
. Grep is an
acronym for "Globally search a Regular Expression and Print." In the simplest
use case, grep
searches a specified file for a specified string using the
following steps:
- Take as arguments a filename and a string.
- Read the file.
- Find lines in the file that contain the string argument.
- Print out those lines.
We'll also show how to use environment variables and print to standard error instead of standard out; these techniques are commonly used in command line tools.
One Rust community member, Andrew Gallant, has already created a
fully-featured, very fast version of grep
, called ripgrep
. By comparison,
our version of grep
will be fairly simple, this chapter will give you some of
the background knowledge to help you understand a real-world project like
ripgrep
.
This project will bring together a number of concepts you've learned so far:
- Organizing code (using what we learned in modules, Chapter 7)
- Using vectors and strings (collections, Chapter 8)
- Handling errors (Chapter 9)
- Using traits and lifetimes where appropriate (Chapter 10)
- Writing tests (Chapter 11)
We'll also briefly introduce closures, iterators, and trait objects, which Chapters 13 and 17 will cover in detail.
Let's create a new project with, as always, cargo new
. We're calling our
project greprs
to distinguish from the grep
tool that you may already have
on your system:
$ cargo new --bin greprs
Created binary (application) `greprs` project
$ cd greprs