Implement grep -F
This commit is contained in:
parent
728f36aa77
commit
6866bcdec8
26
grep.1
26
grep.1
|
@ -3,7 +3,7 @@
|
||||||
grep \- search files for a pattern
|
grep \- search files for a pattern
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B grep
|
.B grep
|
||||||
.RB [ \-EHchilnqsv ]
|
.RB [ \-EFHchilnqsv ]
|
||||||
.RB [ \-e
|
.RB [ \-e
|
||||||
.I pattern ]
|
.I pattern ]
|
||||||
.I pattern
|
.I pattern
|
||||||
|
@ -22,14 +22,18 @@ status code is 2.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.B \-E
|
.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
|
.TP
|
||||||
.B \-H
|
.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.
|
default when there is more than one file specified.
|
||||||
.TP
|
.TP
|
||||||
.B \-c
|
.B \-c
|
||||||
prints only a count of matching lines.
|
Prints only a count of matching lines.
|
||||||
.TP
|
.TP
|
||||||
.B \-e pattern
|
.B \-e pattern
|
||||||
Specify a pattern used during the search of the input: an input
|
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
|
.TP
|
||||||
.B \-h
|
.B \-h
|
||||||
do not prefix each line with 'filename:' prefix.
|
Do not prefix each line with 'filename:' prefix.
|
||||||
.TP
|
.TP
|
||||||
.B \-i
|
.B \-i
|
||||||
matches lines case insensitively.
|
Matches lines case insensitively.
|
||||||
.TP
|
.TP
|
||||||
.B \-l
|
.B \-l
|
||||||
prints only the names of files with matching lines.
|
Prints only the names of files with matching lines.
|
||||||
.TP
|
.TP
|
||||||
.B \-n
|
.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
|
.TP
|
||||||
.B \-q
|
.B \-q
|
||||||
prints nothing, only returns status.
|
Prints nothing, only returns status.
|
||||||
.TP
|
.TP
|
||||||
.B \-s
|
.B \-s
|
||||||
Suppress the error messages ordinarily written for nonexistent or unreadable files.
|
Suppress the error messages ordinarily written for nonexistent or unreadable files.
|
||||||
.TP
|
.TP
|
||||||
.B \-v
|
.B \-v
|
||||||
selects lines which do
|
Selects lines which do
|
||||||
.B not
|
.B not
|
||||||
match the pattern.
|
Match the pattern.
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.IR regex (7)
|
.IR regex (7)
|
||||||
|
|
27
grep.c
27
grep.c
|
@ -14,6 +14,7 @@ enum { Match = 0, NoMatch = 1, Error = 2 };
|
||||||
static void addpattern(const char *);
|
static void addpattern(const char *);
|
||||||
static int grep(FILE *, const char *);
|
static int grep(FILE *, const char *);
|
||||||
|
|
||||||
|
static int Fflag;
|
||||||
static int Hflag;
|
static int Hflag;
|
||||||
static int eflag;
|
static int eflag;
|
||||||
static int hflag;
|
static int hflag;
|
||||||
|
@ -33,7 +34,7 @@ static SLIST_HEAD(phead, pattern) phead;
|
||||||
static void
|
static void
|
||||||
usage(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
|
int
|
||||||
|
@ -49,6 +50,9 @@ main(int argc, char *argv[])
|
||||||
case 'E':
|
case 'E':
|
||||||
flags |= REG_EXTENDED;
|
flags |= REG_EXTENDED;
|
||||||
break;
|
break;
|
||||||
|
case 'F':
|
||||||
|
Fflag = 1;
|
||||||
|
break;
|
||||||
case 'H':
|
case 'H':
|
||||||
Hflag = 1;
|
Hflag = 1;
|
||||||
break;
|
break;
|
||||||
|
@ -88,9 +92,10 @@ main(int argc, char *argv[])
|
||||||
argv++;
|
argv++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compile regex for all search patterns */
|
if (!Fflag)
|
||||||
SLIST_FOREACH(pnode, &phead, entry)
|
/* Compile regex for all search patterns */
|
||||||
enregcomp(Error, &pnode->preg, pnode->pattern, flags);
|
SLIST_FOREACH(pnode, &phead, entry)
|
||||||
|
enregcomp(Error, &pnode->preg, pnode->pattern, flags);
|
||||||
many = (argc > 1);
|
many = (argc > 1);
|
||||||
if (argc == 0) {
|
if (argc == 0) {
|
||||||
match = grep(stdin, "<stdin>");
|
match = grep(stdin, "<stdin>");
|
||||||
|
@ -111,7 +116,8 @@ main(int argc, char *argv[])
|
||||||
while (!SLIST_EMPTY(&phead)) {
|
while (!SLIST_EMPTY(&phead)) {
|
||||||
pnode = SLIST_FIRST(&phead);
|
pnode = SLIST_FIRST(&phead);
|
||||||
SLIST_REMOVE_HEAD(&phead, entry);
|
SLIST_REMOVE_HEAD(&phead, entry);
|
||||||
regfree(&pnode->preg);
|
if (!Fflag)
|
||||||
|
regfree(&pnode->preg);
|
||||||
free(pnode->pattern);
|
free(pnode->pattern);
|
||||||
free(pnode);
|
free(pnode);
|
||||||
}
|
}
|
||||||
|
@ -142,8 +148,15 @@ grep(FILE *fp, const char *str)
|
||||||
if (len && buf[len - 1] == '\n')
|
if (len && buf[len - 1] == '\n')
|
||||||
buf[len - 1] = '\0';
|
buf[len - 1] = '\0';
|
||||||
SLIST_FOREACH(pnode, &phead, entry) {
|
SLIST_FOREACH(pnode, &phead, entry) {
|
||||||
if (regexec(&pnode->preg, buf, 0, NULL, 0) ^ vflag)
|
if (!Fflag) {
|
||||||
continue;
|
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) {
|
switch (mode) {
|
||||||
case 'c':
|
case 'c':
|
||||||
c++;
|
c++;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user