Skip to content

Commit

Permalink
Added more grep support (#29)
Browse files Browse the repository at this point in the history
Added an `egrep` alias, as well as support for `-F`, `-E`, and `-e`
flags.
  • Loading branch information
josephlewis42 authored Dec 24, 2023
1 parent 5f08a52 commit ce70d76
Showing 1 changed file with 33 additions and 9 deletions.
42 changes: 33 additions & 9 deletions commands/grep.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,39 +12,62 @@ import (

// Grep implements the POSIX grep command.
//
// https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/
// https://pubs.opengroup.org/onlinepubs/9699919799/utilities/grep.html
func Grep(virtOS vos.VOS) int {
cmd := &SimpleCommand{
Use: "grep [-iv] PATTERN [FILE]...",
Use: "grep [-E|-F] [-iv] PATTERN [FILE]...",
Short: "Search files for text matching a pattern.",
}

invert := cmd.Flags().Bool('v', "Select lines not matching any of the specified patterns.")
ignoreCase := cmd.Flags().Bool('i', "Perform pattern matching in searches without regard to case.")
showLineNumbers := cmd.Flags().Bool('n', "Show line numbers.")
fixedStrings := cmd.Flags().Bool('F', "Treat patterns as strings rather than regular expressions.")
extendedRegex := cmd.Flags().Bool('E', "Use extended regular expressions.")

var patternList string
patternListFlag := cmd.Flags().Flag(&patternList, 'e', "Pattern to be used during the search for input.")

return cmd.Run(virtOS, func() int {
args := cmd.Flags().Args()
if len(args) == 0 {
// NOTE: Officially, the PATTERN argument supports multiple patterns delimited by newlines.
// It's a very rare case so we'll ignore it here.
var pattern string
switch {
case patternListFlag.Seen():
pattern = patternList

case len(args) == 0:
cmd.LogProgramError(virtOS, errors.New("missing argument PATTERN"))
return 1

default:
pattern = args[0]
args = args[1:]
}

switch {
case *extendedRegex || virtOS.Args()[0] == "egrep":
// Treat the pattern as regex.
case *fixedStrings:
pattern = regexp.QuoteMeta(pattern)
default:
// TODO: grep should treat the normal mode as "basic" regular expressions
// rather than extended: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03
}

// NOTE: Officially, the PATTERN argument supports multiple patterns delimited by newlines.
// It's a very rare case so we'll ignore it here.
pattern := args[0]
if *ignoreCase {
pattern = "(?i)" + pattern
}

regex, err := regexp.Compile(pattern)
if err != nil {
cmd.LogProgramError(virtOS, err)
return 2
}

files := args[1:]
showFileName := len(files) > 1
return cmd.RunEachFileOrStdin(virtOS, files, func(name string, fd io.Reader) error {
showFileName := len(args) > 1
return cmd.RunEachFileOrStdin(virtOS, args, func(name string, fd io.Reader) error {
w := virtOS.Stdout()

scanner := bufio.NewScanner(fd)
Expand Down Expand Up @@ -77,4 +100,5 @@ var _ vos.ProcessFunc = Grep

func init() {
addBinCmd("grep", Grep)
addBinCmd("egrep", Grep)
}

0 comments on commit ce70d76

Please sign in to comment.