Hi, The -m, or --max-count, option allows the user to stop grep(1) processing after a given number of matches are found. If you use constructs such as
$ grep foo foo.txt | head -n1 you will want to use the much faster version $ grep -m1 foo foo.txt This option already exists in at least Linux, FreeBSD and NetBSD. For example, I need grep -m for vimtex (see Issue #1018 on GitHub[0]). But, if I had known that this exists, I would have used it in the past with other scripts. The following diff is adapted from FreeBSD and I tested it with vimtex and a few hand-crafted examples. We could probably do some tricks with mcount and mlimit, but I do not think it is worth it. OK? [0] -- https://github.com/lervag/vimtex/issues/1018 Index: grep.c =================================================================== RCS file: /cvs/src/usr.bin/grep/grep.c,v retrieving revision 1.55 diff -u -p -u -p -r1.55 grep.c --- grep.c 28 Nov 2015 01:17:12 -0000 1.55 +++ grep.c 7 Dec 2017 15:23:00 -0000 @@ -71,6 +71,9 @@ int cflag; /* -c: only show a count of 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) */ @@ -107,9 +110,9 @@ usage(void) { fprintf(stderr, #ifdef NOZ - "usage: %s [-abcEFGHhIiLlnoqRsUVvwx] [-A num] [-B num] [-C[num]]\n" + "usage: %s [-abcEFGHhIiLlmnoqRsUVvwx] [-A num] [-B num] [-C[num]]\n" #else - "usage: %s [-abcEFGHhIiLlnoqRsUVvwxZ] [-A num] [-B num] [-C[num]]\n" + "usage: %s [-abcEFGHhIiLlmnoqRsUVvwxZ] [-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); @@ -117,9 +120,9 @@ usage(void) } #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[] = @@ -147,6 +150,7 @@ 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'}, @@ -375,6 +379,14 @@ main(int argc, char *argv[]) case 'l': Lflag = 0; lflag = qflag = 1; + break; + case 'm': + mflag = 1; + errno = 0; + mlimit = mcount = strtonum(optarg, 1, LLONG_MAX, + &errstr); + if (errstr != NULL) + errx(2, "mcount %s", errstr); break; case 'n': nflag = 1; Index: grep.h =================================================================== RCS file: /cvs/src/usr.bin/grep/grep.h,v retrieving revision 1.24 diff -u -p -u -p -r1.24 grep.h --- grep.h 14 Dec 2015 20:02:07 -0000 1.24 +++ grep.h 7 Dec 2017 15:23:00 -0000 @@ -66,14 +66,17 @@ extern int cflags, eflags; /* 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 char **pattern; 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 Index: util.c =================================================================== RCS file: /cvs/src/usr.bin/grep/util.c,v retrieving revision 1.57 diff -u -p -u -p -r1.57 util.c --- util.c 3 Apr 2017 16:18:35 -0000 1.57 +++ util.c 7 Dec 2017 15:23:00 -0000 @@ -97,6 +97,8 @@ procfile(char *fn) file_t *f; int c, t, z, nottext; + mcount = mlimit; + if (fn == NULL) { fn = "(standard input)"; f = grep_fdopen(STDIN_FILENO, "r"); @@ -140,6 +142,8 @@ procfile(char *fn) linesqueued++; } c += t; + if (mflag && mcount <= 0) + break; } if (Bflag > 0) clearqueue(); @@ -223,6 +227,10 @@ redo: print: 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 */
