From b0dc886d9c1fb5df275b5ea9a95c061a5931e50b Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 21 Jun 2017 13:59:57 -0700 Subject: grep: -m no longer cuts off trailing context Problem reported by Markus Jochim (Bug#26254). * NEWS, doc/grep.texi (General Output Control): Document this. * src/grep.c (prpending): Selected lines no longer cut off context. (usage): Say "selected" instead of "matching", where appropriate. * tests/foad1, tests/max-count-vs-context, tests/yesno: Adjust to match new behavior. --- NEWS | 5 +++++ doc/grep.texi | 10 ++++------ src/grep.c | 29 ++++++++++------------------- tests/foad1 | 8 ++++---- tests/max-count-vs-context | 2 +- tests/yesno | 8 ++++---- 6 files changed, 28 insertions(+), 34 deletions(-) diff --git a/NEWS b/NEWS index 0a8cbbc9..bd2c00a6 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,11 @@ GNU grep NEWS -*- outline -*- ** Changes in behavior + Context no longer excludes selected lines omitted because of -m. + For example, 'grep "^" -m1 -A1' now outputs the first two input + lines, not just the first line. This fixes a glitch that has been + present since -m was added in grep 2.5. + The following changes affect only MS-Windows platforms. First, the --binary (-U) option now governs whether binary I/O is used, instead of a heuristic that was sometimes incorrect. Second, the diff --git a/doc/grep.texi b/doc/grep.texi index 728c039d..334a0593 100644 --- a/doc/grep.texi +++ b/doc/grep.texi @@ -311,11 +311,11 @@ The scanning of each file stops on the first match. @opindex -m @opindex --max-count @cindex max-count -Stop reading a file after @var{num} matching lines. +Stop after the first @var{num} selected lines. If the input is standard input from a regular file, -and @var{num} matching lines are output, +and @var{num} selected lines are output, @command{grep} ensures that the standard input is positioned -just after the last matching line before exiting, +just after the last selected line before exiting, regardless of the presence of trailing context lines. This enables a calling process to resume a search. For example, the following shell script makes use of it: @@ -340,10 +340,8 @@ done @end example @cindex context lines -When @command{grep} stops after @var{num} matching lines, +When @command{grep} stops after @var{num} selected lines, it outputs any trailing context lines. -Since context does not include matching lines, -@command{grep} will stop when it encounters another matching line. When the @option{-c} or @option{--count} option is also used, @command{grep} does not output a count greater than @var{num}. When the @option{-v} or @option{--invert-match} option is also used, diff --git a/src/grep.c b/src/grep.c index bc2599f3..8d22aec3 100644 --- a/src/grep.c +++ b/src/grep.c @@ -1011,7 +1011,7 @@ static intmax_t out_before; /* Lines of leading context. */ static intmax_t out_after; /* Lines of trailing context. */ static bool count_matches; /* Count matching lines. */ static bool no_filenames; /* Suppress file names. */ -static intmax_t max_count; /* Stop after outputting this many +static intmax_t max_count; /* Max number of selected lines from an input file. */ static bool line_buffered; /* Use line buffering. */ static char *label = NULL; /* Fake filename for stdin */ @@ -1023,7 +1023,7 @@ static char const *lastnl; /* Pointer after last newline counted. */ static char *lastout; /* Pointer after last character output; NULL if no character has been output or if it's conceptually before bufbeg. */ -static intmax_t outleft; /* Maximum number of lines to be output. */ +static intmax_t outleft; /* Maximum number of selected lines. */ static intmax_t pending; /* Pending lines of output. Always kept 0 if out_quiet is true. */ static bool done_on_match; /* Stop scanning file on first match. */ @@ -1276,25 +1276,16 @@ prline (char *beg, char *lim, char sep) lastout = lim; } -/* Print pending lines of trailing context prior to LIM. Trailing context ends - at the next matching line when OUTLEFT is 0. */ +/* Print pending lines of trailing context prior to LIM. */ static void prpending (char const *lim) { if (!lastout) lastout = bufbeg; - while (pending > 0 && lastout < lim) + for (; 0 < pending && lastout < lim; pending--) { char *nl = memchr (lastout, eolbyte, lim - lastout); - size_t match_size; - --pending; - if (outleft - || ((execute (compiled_pattern, lastout, nl + 1 - lastout, - &match_size, NULL) == (size_t) -1) - == !out_invert)) - prline (lastout, nl + 1, SEP_CHAR_REJECTED); - else - pending = 0; + prline (lastout, nl + 1, SEP_CHAR_REJECTED); } } @@ -1949,11 +1940,11 @@ Miscellaneous:\n\ printf (_("\ \n\ Output control:\n\ - -m, --max-count=NUM stop after NUM matches\n\ + -m, --max-count=NUM stop after NUM selected lines\n\ -b, --byte-offset print the byte offset with output lines\n\ -n, --line-number print line number with output lines\n\ --line-buffered flush output on every line\n\ - -H, --with-filename print the file name for each match\n\ + -H, --with-filename print file name with output lines\n\ -h, --no-filename suppress the file name prefix on output\n\ --label=LABEL use LABEL as the standard input file name prefix\n\ ")); @@ -1981,9 +1972,9 @@ Output control:\n\ --exclude-dir=PATTERN directories that match PATTERN will be skipped.\n\ ")); printf (_("\ - -L, --files-without-match print only names of FILEs containing no match\n\ - -l, --files-with-matches print only names of FILEs containing matches\n\ - -c, --count print only a count of matching lines per FILE\n\ + -L, --files-without-match print only names of FILEs with no selected lines\n\ + -l, --files-with-matches print only names of FILEs with selected lines\n\ + -c, --count print only a count of selected lines per FILE\n\ -T, --initial-tab make tabs line up (if needed)\n\ -Z, --null print 0 byte after FILE name\n")); printf (_("\ diff --git a/tests/foad1 b/tests/foad1 index 0163f1a1..e3999819 100755 --- a/tests/foad1 +++ b/tests/foad1 @@ -93,12 +93,12 @@ grep_test "wordword/" "${CB}word${CE}word/" "\ exp || framework_failure_ +sed 6q in > exp || framework_failure_ fail=0 grep -m1 -A5 needle in > out 2>err || fail=1 diff --git a/tests/yesno b/tests/yesno index e379c19b..1ae2142f 100755 --- a/tests/yesno +++ b/tests/yesno @@ -73,14 +73,14 @@ set x \ '-C,1,--no-gr' "$rB$C$D$E$rF$rG$H$I$rJ$rL$M$N$z0" \ '-m,4' "$C$D$E$H$z0$XI$XJ$XK$XL$XM$XN" \ '-m,4,-o' "$c$d$e$h$z0$XI$XJ$XK$XL$XM$XN" \ - '-m,4,-C,1' "$rB$C$D$E$rF$rG$H$z0$XI$XJ$XK$XL$XM$XN" \ + '-m,4,-C,1' "$rB$C$D$E$rF$rG$H$rI$z0$XI$XJ$XK$XL$XM$XN" \ '-m,4,-C,1,-o' "$c$d$e$h$z0$XI$XJ$XK$XL$XM$XN" \ '-m,5' "$C$D$E$H$I$z0$XJ$XK$XL$XM$XN" \ '-m,5,-o' "$c$d$e$h$i$z0$XJ$XK$XL$XM$XN" \ '-m,5,-C,1,-o' "$c$d$e$h$i$z0$XJ$XK$XL$XM$XN" \ '-m,6' "$C$D$E$H$I$M$z0$XN" \ '-m,6,-o' "$c$d$e$h$i$m$z0$XN" \ - '-m,6,-C,1' "$rB$C$D$E$rF$rG$H$I$rJ$s$rL$M$z0$XN" \ + '-m,6,-C,1' "$rB$C$D$E$rF$rG$H$I$rJ$s$rL$M$rN$z0$XN" \ '-m,6,-C,1,-o' "$c$d$e$h$i$s$m$z0$XN" \ '-v' "$A$B$F$G$J$K$L$z0" \ '-v,-o' "$z0" \ @@ -92,13 +92,13 @@ set x \ '-4,-v,-1' "$A$B$rC$s$rE$F$G$rH$rI$J$K$L$rM$z0" \ '-m,1,-v' "$A$z0$XB$XC$XD$XE$XF$XG$XH$XI$XJ$XK$XL$XM$XN" \ '-m,1,-v,-o' "$z0$XB$XC$XD$XE$XF$XG$XH$XI$XJ$XK$XL$XM$XN" \ - '-m,1,-v,-C,1' "$A$z0$XB$XC$XD$XE$XF$XG$XH$XI$XJ$XK$XL$XM$XN" \ + '-m,1,-v,-C,1' "$A$rB$z0$XB$XC$XD$XE$XF$XG$XH$XI$XJ$XK$XL$XM$XN" \ '-m,1,-v,-C,1,-o' "$z0$XB$XC$XD$XE$XF$XG$XH$XI$XJ$XK$XL$XM$XN" \ '-m,2,-v' "$A$B$z0$XC$XD$XE$XF$XG$XH$XI$XJ$XK$XL$XM$XN" \ '-m,2,-v,-o' "$z0$XC$XD$XE$XF$XG$XH$XI$XJ$XK$XL$XM$XN" \ '-m,3,-v' "$A$B$F$z0$XG$XH$XI$XJ$XK$XL$XM$XN" \ '-m,3,-v,-o' "$z0$XG$XH$XI$XJ$XK$XL$XM$XN" \ - '-m,3,-v,-C,1' "$A$B$rC$s$rE$F$z0$XG$XH$XI$XJ$XK$XL$XM$XN" \ + '-m,3,-v,-C,1' "$A$B$rC$s$rE$F$rG$z0$XG$XH$XI$XJ$XK$XL$XM$XN" \ '-m,3,-v,-C,1,-o' "$rc$s$re$z0$XG$XH$XI$XJ$XK$XL$XM$XN" \ x shift -- cgit v1.2.1