commit 7627a5069cb14c66d8ba964e4a02ce5b56ff6180
parent e34ce441928a4670b5e62c0fa8f0f0f7ce631965
Author: sin <sin@2f30.org>
Date: Thu, 20 Nov 2014 14:47:26 +0000
Implement grep -x
Diffstat:
2 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/grep.1 b/grep.1
@@ -3,7 +3,7 @@
grep \- search files for a pattern
.SH SYNOPSIS
.B grep
-.RB [ \-EFHchilnqsv ]
+.RB [ \-EFHchilnqsvx ]
.RB [ \-e
.I pattern ]
.I pattern
@@ -64,5 +64,9 @@ Suppress the error messages ordinarily written for nonexistent or unreadable fil
Selects lines which do
.B not
Match the pattern.
+.TP
+.B \-x
+Consider only input lines that use all characters in the line excluding the terminating <newline> to
+match an entire fixed string or regular expression to be matching lines.
.SH SEE ALSO
.IR regex (7)
diff --git a/grep.c b/grep.c
@@ -20,6 +20,7 @@ static int eflag;
static int hflag;
static int sflag;
static int vflag;
+static int xflag;
static int many;
static char mode;
@@ -34,7 +35,7 @@ static SLIST_HEAD(phead, pattern) phead;
static void
usage(void)
{
- enprintf(Error, "usage: %s [-EFHcilnqsv] [-e pattern] pattern [files...]\n", argv0);
+ enprintf(Error, "usage: %s [-EFHcilnqsvx] [-e pattern] pattern [files...]\n", argv0);
}
int
@@ -78,6 +79,9 @@ main(int argc, char *argv[])
case 'v':
vflag = 1;
break;
+ case 'x':
+ xflag = 1;
+ break;
default:
usage();
} ARGEND;
@@ -128,9 +132,19 @@ static void
addpattern(const char *pattern)
{
struct pattern *pnode;
+ char *tmp;
pnode = emalloc(sizeof(*pnode));
- pnode->pattern = estrdup(pattern);
+ if (!Fflag && xflag) {
+ tmp = emalloc(strlen(pattern) + 3);
+ snprintf(tmp, strlen(pattern) + 3, "%s%s%s",
+ pattern[0] == '^' ? "" : "^",
+ pattern,
+ pattern[strlen(pattern) - 1] == '$' ? "" : "$");
+ pnode->pattern = tmp;
+ } else {
+ pnode->pattern = estrdup(pattern);
+ }
SLIST_INSERT_HEAD(&phead, pnode, entry);
}
@@ -152,7 +166,10 @@ grep(FILE *fp, const char *str)
if (regexec(&pnode->preg, buf, 0, NULL, 0) ^ vflag)
continue;
} else {
- match = strstr(buf, pnode->pattern) ? Match : NoMatch;
+ if (!xflag)
+ match = strstr(buf, pnode->pattern) ? Match : NoMatch;
+ else
+ match = strcmp(buf, pnode->pattern);
if (match ^ vflag)
continue;
}