Implement grep -f

This commit is contained in:
sin 2014-11-20 16:57:49 +00:00
parent 5ba4f37ec3
commit a1844fae70
2 changed files with 37 additions and 11 deletions

8
grep.1
View File

@ -6,6 +6,8 @@ grep \- search files for a pattern
.RB [ \-EFHchilnqsvx ] .RB [ \-EFHchilnqsvx ]
.RB [ \-e .RB [ \-e
.I pattern ] .I pattern ]
.RB [ \-f
.I file ]
.I pattern .I pattern
.RI [ file ...] .RI [ file ...]
.SH DESCRIPTION .SH DESCRIPTION
@ -40,6 +42,12 @@ Specify a pattern used during the search of the input: an input
line is selected if it matches any of the specified patterns. line is selected if it matches any of the specified patterns.
This option is most useful when multiple -e options are used to This option is most useful when multiple -e options are used to
specify multiple patterns, or when a pattern begins with a dash specify multiple patterns, or when a pattern begins with a dash
.TP
.B \-f file
Read one or more patterns from the file named by the pathname file.
Patterns in file shall be terminated by a <newline>. A null pattern can be
specified by an empty line in pattern_file. Unless the -E or -F option is
also specified, each pattern shall be treated as a BRE.
(`-'). (`-').
.TP .TP
.B \-h .B \-h

40
grep.c
View File

@ -12,11 +12,13 @@
enum { Match = 0, NoMatch = 1, Error = 2 }; enum { Match = 0, NoMatch = 1, Error = 2 };
static void addpattern(const char *); static void addpattern(const char *);
static void addpatternfile(const char *);
static int grep(FILE *, const char *); static int grep(FILE *, const char *);
static int Fflag; static int Fflag;
static int Hflag; static int Hflag;
static int eflag; static int eflag;
static int fflag;
static int hflag; static int hflag;
static int sflag; static int sflag;
static int vflag; static int vflag;
@ -35,7 +37,7 @@ static SLIST_HEAD(phead, pattern) phead;
static void static void
usage(void) usage(void)
{ {
enprintf(Error, "usage: %s [-EFHcilnqsvx] [-e pattern] pattern [files...]\n", argv0); enprintf(Error, "usage: %s [-EFHcilnqsvx] [-e pattern] [-f file] pattern [files...]\n", argv0);
} }
int int
@ -61,6 +63,10 @@ main(int argc, char *argv[])
addpattern(EARGF(usage())); addpattern(EARGF(usage()));
eflag = 1; eflag = 1;
break; break;
case 'f':
addpatternfile(EARGF(usage()));
fflag = 1;
break;
case 'h': case 'h':
hflag = 1; hflag = 1;
break; break;
@ -86,11 +92,11 @@ main(int argc, char *argv[])
usage(); usage();
} ARGEND; } ARGEND;
if (argc == 0 && !eflag) if (argc == 0 && !eflag && !fflag)
usage(); /* no pattern */ usage(); /* no pattern */
/* If -e is not specified treat it as if it were */ /* just add literal pattern to list */
if (!eflag) { if (!eflag && !fflag) {
addpattern(argv[0]); addpattern(argv[0]);
argc--; argc--;
argv++; argv++;
@ -149,18 +155,30 @@ addpattern(const char *pattern)
tmp = estrdup(pattern); tmp = estrdup(pattern);
} }
SLIST_FOREACH(pnode, &phead, entry) {
if (!strcmp(pnode->pattern, tmp)) {
free(tmp);
return;
}
}
pnode = emalloc(sizeof(*pnode)); pnode = emalloc(sizeof(*pnode));
pnode->pattern = tmp; pnode->pattern = tmp;
SLIST_INSERT_HEAD(&phead, pnode, entry); SLIST_INSERT_HEAD(&phead, pnode, entry);
} }
static void
addpatternfile(const char *file)
{
FILE *fp;
char *buf = NULL;
size_t len = 0, size = 0;
fp = fopen(file, "r");
if (!fp)
enprintf(Error, "fopen %s:", file);
while ((len = getline(&buf, &size, fp)) != -1) {
if (len && buf[len - 1] == '\n')
buf[len - 1] = '\0';
addpattern(buf);
}
free(buf);
fclose(fp);
}
static int static int
grep(FILE *fp, const char *str) grep(FILE *fp, const char *str)
{ {