grep -m num stops after a maximum of num matches are found.
We support -m0 to match GNU behaviour, but we do not allow negative
numbers.
Manpage help from jmc@, OK deraadt@.
-.\" $OpenBSD: grep.1,v 1.43 2015/01/13 04:45:34 daniel Exp $
+.\" $OpenBSD: grep.1,v 1.44 2017/12/09 18:38:37 pirofti Exp $
.\" Copyright (c) 1980, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\"
.\" @(#)grep.1 8.3 (Berkeley) 4/18/94
.\"
-.Dd $Mdocdate: January 13 2015 $
+.Dd $Mdocdate: December 9 2017 $
.Dt GREP 1
.Os
.Sh NAME
.Op Fl C Ns Op Ar num
.Op Fl e Ar pattern
.Op Fl f Ar file
+.Op Fl m Ar num
.Op Fl -binary-files Ns = Ns Ar value
.Op Fl -context Ns Op = Ns Ar num
.Op Fl -line-buffered
If the standard input is searched, the string
.Dq (standard input)
is written.
+.It Fl m Ar num, Fl Fl max-count Ns = Ns Ar num
+Stop after
+.Ar num
+matches.
.It Fl n
Each output line is preceded by its relative line number in the file,
starting at line 1.
specification.
.Pp
The flags
-.Op Fl AaBbCGHhILoRUVwZ
+.Op Fl AaBbCGHhILmoRUVwZ
are extensions to that specification, and the behaviour of the
.Fl f
flag when used with an empty pattern file is left undefined.
-/* $OpenBSD: grep.c,v 1.55 2015/11/28 01:17:12 gsoares Exp $ */
+/* $OpenBSD: grep.c,v 1.56 2017/12/09 18:38:37 pirofti Exp $ */
/*-
* Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
int hflag; /* -h: don't print filename headers */
int iflag; /* -i: ignore case */
int lflag; /* -l: only show names of files with matches */
+int mflag; /* -m x: stop reading the files after x matches */
+long long mcount; /* count for -m */
+long long mlimit; /* requested value for -m */
int nflag; /* -n: show line numbers in front of matching lines */
int oflag; /* -o: print each match */
int qflag; /* -q: quiet mode (don't output anything) */
#else
"usage: %s [-abcEFGHhIiLlnoqRsUVvwxZ] [-A num] [-B num] [-C[num]]\n"
#endif
- "\t[-e pattern] [-f file] [--binary-files=value] [--context[=num]]\n"
- "\t[--line-buffered] [pattern] [file ...]\n", __progname);
+ "\t[-e pattern] [-f file] [-m num] [--binary-files=value]\n"
+ "\t[--context[=num]] [--line-buffered] [pattern] [file ...]\n",
+ __progname);
exit(2);
}
#ifdef NOZ
-static const char optstr[] = "0123456789A:B:CEFGHILRUVabce:f:hilnoqrsuvwxy";
+static const char optstr[] = "0123456789A:B:CEFGHILRUVabce:f:hilm:noqrsuvwxy";
#else
-static const char optstr[] = "0123456789A:B:CEFGHILRUVZabce:f:hilnoqrsuvwxy";
+static const char optstr[] = "0123456789A:B:CEFGHILRUVZabce:f:hilm:noqrsuvwxy";
#endif
static const struct option long_options[] =
{"ignore-case", no_argument, NULL, 'i'},
{"files-without-match", no_argument, NULL, 'L'},
{"files-with-matches", no_argument, NULL, 'l'},
+ {"max-count", required_argument, NULL, 'm'},
{"line-number", no_argument, NULL, 'n'},
{"quiet", no_argument, NULL, 'q'},
{"silent", no_argument, NULL, 'q'},
Lflag = 0;
lflag = qflag = 1;
break;
+ case 'm':
+ mflag = 1;
+ mlimit = mcount = strtonum(optarg, 0, LLONG_MAX,
+ &errstr);
+ if (errstr != NULL)
+ errx(2, "invalid max-count %s: %s",
+ optarg, errstr);
+ break;
case 'n':
nflag = 1;
break;
-/* $OpenBSD: grep.h,v 1.24 2015/12/14 20:02:07 mmcc Exp $ */
+/* $OpenBSD: grep.h,v 1.25 2017/12/09 18:38:37 pirofti Exp $ */
/*-
* Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
/* Command line flags */
extern int Aflag, Bflag, Eflag, Fflag, Hflag, Lflag,
Rflag, Zflag,
- bflag, cflag, hflag, iflag, lflag, nflag, oflag, qflag, sflag,
- vflag, wflag, xflag;
+ bflag, cflag, hflag, iflag, lflag, mflag, nflag, oflag, qflag,
+ sflag, vflag, wflag, xflag;
extern int binbehave;
extern int first, matchall, patterns, tail, file_err;
extern fastgrep_t *fg_pattern;
extern regex_t *r_pattern;
+/* For -m max-count */
+extern long long mcount, mlimit;
+
/* For regex errors */
#define RE_ERROR_BUF 512
extern char re_error[RE_ERROR_BUF + 1]; /* Seems big enough */
-/* $OpenBSD: util.c,v 1.57 2017/04/03 16:18:35 tedu Exp $ */
+/* $OpenBSD: util.c,v 1.58 2017/12/09 18:38:37 pirofti Exp $ */
/*-
* Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
file_t *f;
int c, t, z, nottext;
+ mcount = mlimit;
+
if (fn == NULL) {
fn = "(standard input)";
f = grep_fdopen(STDIN_FILENO, "r");
if (Bflag > 0)
initqueue();
for (c = 0; c == 0 || !(lflag || qflag); ) {
+ if (mflag && mlimit == 0)
+ break;
ln.off += ln.len + 1;
if ((ln.dat = grep_fgetln(f, &ln.len)) == NULL)
break;
linesqueued++;
}
c += t;
+ if (mflag && mcount <= 0)
+ break;
}
if (Bflag > 0)
clearqueue();
if (vflag)
c = !c;
+ /* Count the matches if we have a match limit */
+ if (mflag)
+ mcount -= c;
+
if (c && binbehave == BIN_FILE_BIN && nottext)
return c; /* Binary file */