sbase

suckless unix tools
git clone git://git.2f30.org/sbase
Log | Files | Refs | README | LICENSE

commit 6866bcdec8d8fc7c42e18ebc7e0bd350db91e4f0
parent 728f36aa77215b6ad919bbc6e13ff22cf3f81809
Author: sin <sin@2f30.org>
Date:   Thu, 20 Nov 2014 14:35:23 +0000

Implement grep -F

Diffstat:
Mgrep.1 | 26+++++++++++++++-----------
Mgrep.c | 27++++++++++++++++++++-------
2 files changed, 35 insertions(+), 18 deletions(-)

diff --git a/grep.1 b/grep.1 @@ -3,7 +3,7 @@ grep \- search files for a pattern .SH SYNOPSIS .B grep -.RB [ \-EHchilnqsv ] +.RB [ \-EFHchilnqsv ] .RB [ \-e .I pattern ] .I pattern @@ -22,14 +22,18 @@ status code is 2. .SH OPTIONS .TP .B \-E -matches using extended regex. +Matches using extended regex. +.TP +.B \-F +Match using fixed strings. Treat each pattern specified as a string instead of a regular +expression. .TP .B \-H -prefixes each matching line with its filename in the output. This is the +Prefixes each matching line with its filename in the output. This is the default when there is more than one file specified. .TP .B \-c -prints only a count of matching lines. +Prints only a count of matching lines. .TP .B \-e pattern Specify a pattern used during the search of the input: an input @@ -39,26 +43,26 @@ specify multiple patterns, or when a pattern begins with a dash (`-'). .TP .B \-h -do not prefix each line with 'filename:' prefix. +Do not prefix each line with 'filename:' prefix. .TP .B \-i -matches lines case insensitively. +Matches lines case insensitively. .TP .B \-l -prints only the names of files with matching lines. +Prints only the names of files with matching lines. .TP .B \-n -prefixes each matching line with its line number in the input. +Prefixes each matching line with its line number in the input. .TP .B \-q -prints nothing, only returns status. +Prints nothing, only returns status. .TP .B \-s Suppress the error messages ordinarily written for nonexistent or unreadable files. .TP .B \-v -selects lines which do +Selects lines which do .B not -match the pattern. +Match the pattern. .SH SEE ALSO .IR regex (7) diff --git a/grep.c b/grep.c @@ -14,6 +14,7 @@ enum { Match = 0, NoMatch = 1, Error = 2 }; static void addpattern(const char *); static int grep(FILE *, const char *); +static int Fflag; static int Hflag; static int eflag; static int hflag; @@ -33,7 +34,7 @@ static SLIST_HEAD(phead, pattern) phead; static void usage(void) { - enprintf(Error, "usage: %s [-EHcilnqsv] [-e pattern] pattern [files...]\n", argv0); + enprintf(Error, "usage: %s [-EFHcilnqsv] [-e pattern] pattern [files...]\n", argv0); } int @@ -49,6 +50,9 @@ main(int argc, char *argv[]) case 'E': flags |= REG_EXTENDED; break; + case 'F': + Fflag = 1; + break; case 'H': Hflag = 1; break; @@ -88,9 +92,10 @@ main(int argc, char *argv[]) argv++; } - /* Compile regex for all search patterns */ - SLIST_FOREACH(pnode, &phead, entry) - enregcomp(Error, &pnode->preg, pnode->pattern, flags); + if (!Fflag) + /* Compile regex for all search patterns */ + SLIST_FOREACH(pnode, &phead, entry) + enregcomp(Error, &pnode->preg, pnode->pattern, flags); many = (argc > 1); if (argc == 0) { match = grep(stdin, "<stdin>"); @@ -111,7 +116,8 @@ main(int argc, char *argv[]) while (!SLIST_EMPTY(&phead)) { pnode = SLIST_FIRST(&phead); SLIST_REMOVE_HEAD(&phead, entry); - regfree(&pnode->preg); + if (!Fflag) + regfree(&pnode->preg); free(pnode->pattern); free(pnode); } @@ -142,8 +148,15 @@ grep(FILE *fp, const char *str) if (len && buf[len - 1] == '\n') buf[len - 1] = '\0'; SLIST_FOREACH(pnode, &phead, entry) { - if (regexec(&pnode->preg, buf, 0, NULL, 0) ^ vflag) - continue; + if (!Fflag) { + if (regexec(&pnode->preg, buf, 0, NULL, 0) ^ vflag) + continue; + } else { + match = strstr(buf, pnode->pattern) ? Match : NoMatch; + match ^= vflag; + if (match) + continue; + } switch (mode) { case 'c': c++;