Grep

September 25, 2009

Grep is the quintessential unix utility: it has a funny name, has more command-line switches than a Swiss Army knife has blades, and dates to prehistoric times. In its simplest incarnation, grep takes a regular expression and a file and prints those lines of the file that match the regular expression.

Since we wrote a regular-expression matcher in the three previous exercises, it is easy to write our own version of grep. We’ll keep it simple:

grep [-v] regex [file ...]

The -v flag inverts the sense of the match: print only those lines that do not match the regular expression. One or more files may be named on the command line; if so, the filename is printed before each matching (or non-matching, for -v) line. If no filename is given, grep reads from standard input. All output goes to standard output.

Your task is to write grep. When you are finished, you are welcome to read or run a suggested solution, or to post your solution or discuss the exercise in the comments below.

Pages: 1 2

2 Responses to “Grep”

  1. […] today’s Programming Praxis exercise we’re supposed to implement grep based on the regex matching […]

  2. Remco Niemeijer said

    My Haskell solution (see http://bonsaicode.wordpress.com/2009/09/25/programming-praxis-grep/ for a version with comments):

    import System.Environment
    import Text.Printf
    
    --Code from the previous two exercises goes here
    
    grepString :: Bool -> Maybe String -> [Chunk] -> String -> IO ()
    grepString b p cs = mapM_ (printf "%s%s\n" $ maybe "" (++ ": ") p) .
                        filter ((== b) . match cs) . lines
    
    grep :: Bool -> [String] -> IO ()
    grep _ []     = error "Not enough arguments provided"
    grep b (r:ps) = either print (f ps) $ parseRegex r where
        f [] cs = grepString b Nothing cs =<< getLine
        f _  cs = mapM_ (\p -> grepString b (Just p) cs =<< readFile p) ps
    
    main :: IO ()
    main = f =<< getArgs where
               f ("-v":args) = grep False args
               f args        = grep True  args
    

Leave a comment