commit a1844fae70993122005e138f68937255da0f091c
parent 5ba4f37ec3c4dc0d47bc39662d99e8ce005639ba
Author: sin <sin@2f30.org>
Date: Thu, 20 Nov 2014 16:57:49 +0000
Implement grep -f
Diffstat:
M | grep.1 | | | 8 | ++++++++ |
M | grep.c | | | 40 | +++++++++++++++++++++++++++++----------- |
2 files changed, 37 insertions(+), 11 deletions(-)
diff --git a/grep.1 b/grep.1
@@ -6,6 +6,8 @@ grep \- search files for a pattern
.RB [ \-EFHchilnqsvx ]
.RB [ \-e
.I pattern ]
+.RB [ \-f
+.I file ]
.I pattern
.RI [ file ...]
.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.
This option is most useful when multiple -e options are used to
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
.B \-h
diff --git a/grep.c b/grep.c
@@ -12,11 +12,13 @@
enum { Match = 0, NoMatch = 1, Error = 2 };
static void addpattern(const char *);
+static void addpatternfile(const char *);
static int grep(FILE *, const char *);
static int Fflag;
static int Hflag;
static int eflag;
+static int fflag;
static int hflag;
static int sflag;
static int vflag;
@@ -35,7 +37,7 @@ static SLIST_HEAD(phead, pattern) phead;
static 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
@@ -61,6 +63,10 @@ main(int argc, char *argv[])
addpattern(EARGF(usage()));
eflag = 1;
break;
+ case 'f':
+ addpatternfile(EARGF(usage()));
+ fflag = 1;
+ break;
case 'h':
hflag = 1;
break;
@@ -86,11 +92,11 @@ main(int argc, char *argv[])
usage();
} ARGEND;
- if (argc == 0 && !eflag)
+ if (argc == 0 && !eflag && !fflag)
usage(); /* no pattern */
- /* If -e is not specified treat it as if it were */
- if (!eflag) {
+ /* just add literal pattern to list */
+ if (!eflag && !fflag) {
addpattern(argv[0]);
argc--;
argv++;
@@ -149,18 +155,30 @@ addpattern(const char *pattern)
tmp = estrdup(pattern);
}
- SLIST_FOREACH(pnode, &phead, entry) {
- if (!strcmp(pnode->pattern, tmp)) {
- free(tmp);
- return;
- }
- }
-
pnode = emalloc(sizeof(*pnode));
pnode->pattern = tmp;
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
grep(FILE *fp, const char *str)
{