commit 6866bcdec8d8fc7c42e18ebc7e0bd350db91e4f0
parent 728f36aa77215b6ad919bbc6e13ff22cf3f81809
Author: sin <sin@2f30.org>
Date: Thu, 20 Nov 2014 14:35:23 +0000
Implement grep -F
Diffstat:
M | grep.1 | | | 26 | +++++++++++++++----------- |
M | grep.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++;