[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [bug #28588] -m breaks -A

From: Jim Meyering
Subject: Re: [bug #28588] -m breaks -A
Date: Thu, 04 Feb 2010 08:49:20 +0100

Markus Jochim wrote:
>   <http://savannah.gnu.org/bugs/?28588>
>                  Summary: -m breaks -A
>                  Project: grep
>             Submitted by: angus
> Details:
> I've created a sample input file to show the bug I've encountered in GNU
> grep.
> sample.input:
> attention
> this is the first
> while this looks like the second
> and this smells of third
> attention
> fourth
> Doing `grep -m 1 attention sample.input` behaves as expected. Just so do
> `grep -m 1 -A {1,2,3} attention sample.input`. But as soon as I increase the
> lines of trailing context to four or more, grep will crop the output.
> $ grep -m 1 -A 5 attention sample.input
> attention
> this is the first
> while this looks like the second
> and this smells of third
> Apparently, any non-first (for -m 1) occurence of the pattern is dropped even
> though it is part of the "five lines of trailing context" and must therefore
> be displayed.

Thank you for the report.
At first I thought that was a bug, too.
But it appears to be documented: (this is from "info grep"):

    `-m NUM'
         Stop reading a file after NUM matching lines.  If the input is
         standard input from a regular file, and NUM matching lines are
         output, `grep' ensures that the standard input is positioned just
         after the last matching 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:

              while grep -m 1 PATTERN
                echo xxxx
              done < FILE

         But the following probably will not work because a pipe is not a
         regular file:

              # This probably will not work.
              cat FILE |
              while grep -m 1 PATTERN
                echo xxxx

         When `grep' stops after NUM matching lines, it outputs any
         trailing context lines.  Since context does not include matching
         lines, `grep' will stop when it encounters another matching line.
         When the `-c' or `--count' option is also used, `grep' does not
         output a count greater than NUM.  When the `-v' or
         `--invert-match' option is also used, `grep' stops after
         outputting NUM non-matching lines.

However, since I doubt anyone relies on this unintuitive behavior,
and I do not see how it would be useful to provide less context
that requested in this case, I may well change it.
Comments welcome.

In the mean time, I've added a test case to exercise
the offending behavior.  Here it is, though note that it
depends on a few preceding patches.  I'll push them all

>From 5cf71c8a420697ba59a8219d892473a02892fb6c Mon Sep 17 00:00:00 2001
From: Jim Meyering <address@hidden>
Date: Thu, 14 Jan 2010 08:17:58 +0100
Subject: [PATCH] tests: exercise surprising -m1 vs. --context behavior

* tests/max-count-vs-context: New test.  Exercise the surprising,
but documented, behavior reported by Markus Jochim in
* tests/Makefile.am (TESTS): Add it.
 tests/Makefile.am          |    1 +
 tests/max-count-vs-context |   24 ++++++++++++++++++++++++
 2 files changed, 25 insertions(+), 0 deletions(-)
 create mode 100755 tests/max-count-vs-context

diff --git a/tests/Makefile.am b/tests/Makefile.am
index a76094a..223c181 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -23,6 +23,7 @@ TESTS =               \
   fmbtest.sh   \
   foad1.sh     \
   khadafy.sh   \
+  max-count-vs-context \
   options.sh   \
   pcre.sh      \
   spencer1.sh  \
diff --git a/tests/max-count-vs-context b/tests/max-count-vs-context
new file mode 100755
index 0000000..f10e26b
--- /dev/null
+++ b/tests/max-count-vs-context
@@ -0,0 +1,24 @@
+# Show how -m1 works with -A N when a 2nd match is < N lines after the first
+: ${srcdir=.}
+. "$srcdir/init.sh"; path_prepend_ ../src
+cat <<EOF > in || framework_failure
+1st line of context
+2nd line of context
+3rd line of context
+another needle
+5th line of context relative to first match
+6th line...
+sed 4q in > exp || framework_failure
+grep -m1 -A5 needle in > out 2>err || fail=1
+compare out exp || fail=1
+compare err /dev/null || fail=1
+Exit $fail

reply via email to

[Prev in Thread] Current Thread [Next in Thread]