Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the m option (from grep). #93

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions doc/agrep.1.in
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This entire hunk is plagiarized from the GNU grep manual and cannot be used. Not just because of the blatant copyright violation, but also because it does not accurately describe the added functionality.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it was included by accident I think, sorry for that m(_ _)m

I had decided to not include any change to the manual page, but it must have slip through somehow.
Also, I don't get why there are so many changes...

Sorry again, as I said below, you can safely ignore this PR.

Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,52 @@ environment variable. The default color is red.
Only print a count of matching records per each input file,
suppressing normal output.
.TP
.BI \-m " NUM" "\fR,\fP \-\^\-max\-count=" NUM
Stop reading a file after
.I NUM
matching lines.
If
.I NUM
is zero,
.B agrep
stops right away without reading input.
A
.I NUM
of \-1 is treated as infinity and
.B agrep
does not stop; this is the default.
If the input is standard input from a regular file,
and
.I NUM
matching lines are output,
.B agrep
ensures that the standard input is positioned to 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.
When
.B agrep
stops after
.I NUM
matching lines, it outputs any trailing context lines.
When the
.B \-c
or
.B \-\^\-count
option is also used,
.B agrep
does not output a count greater than
.IR NUM .
When the
.B \-v
or
.B \-\^\-invert\-match
option is also used,
.B agrep
stops after outputting
.I NUM
non-matching lines.
.TP
.BR \-h ", " \-\^\-no\-filename
Suppress the prefixing filename on output when multiple files are
searched.
Expand Down
20 changes: 19 additions & 1 deletion src/agrep.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

/* Short options. */
static char const short_options[] =
"cd:e:hiklnqsvwyBD:E:HI:MS:V0123456789-:";
"cd:e:hiklm:nqsvwyBD:E:HI:MS:V0123456789-:";

static int show_help;
char *program_name;
Expand Down Expand Up @@ -72,6 +72,7 @@ static struct option const long_options[] =
{"insert-cost", required_argument, NULL, 'I'},
{"invert-match", no_argument, NULL, 'v'},
{"line-number", no_argument, NULL, 'n'},
{"max-count", required_argument, NULL, 'm'},
{"literal", no_argument, NULL, 'k'},
{"max-errors", required_argument, NULL, 'E'},
{"no-filename", no_argument, NULL, 'h'},
Expand Down Expand Up @@ -139,6 +140,7 @@ Output control:\n\
-H, --with-filename print the filename for each match\n\
-l, --files-with-matches only print FILE names containing matches\n\
-M, --delimiter-after print record delimiter after record if -d is used\n\
-m, --max-count=NUM stop after NUM selected lines\n\
-n, --record-number print record number with output\n\
--line-number same as -n\n\
-q, --quiet, --silent suppress all normal output\n\
Expand Down Expand Up @@ -185,6 +187,8 @@ static int print_filename; /* Output filename. */
static int print_recnum; /* Output record number. */
static int print_cost; /* Output match cost. */
static int count_matches; /* Count matching records. */
static int max_count; /* Max number of selected
lines from an input file. */
static int list_files; /* List matching files. */
static int color_option; /* Highlight matches. */
static int print_position; /* Show start and end offsets for matches. */
Expand Down Expand Up @@ -449,6 +453,11 @@ tre_agrep_handle_file(const char *filename)
printf("%.*s", record_len, record);
}
}
/* exit after max_count match(es) */
if((max_count > 0)&&(count > (max_count-1))) {
if(count_matches) break;/* to get the result */
else exit(0);/* to leave the stream "as is" */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exiting here produces the wrong result when multiple inputs are provided and at least one of them has max_count or more matching lines. The correct thing to do is break in all cases. Moreover, we're reading from a file descriptor, not a stream, and since we read a variable amount of data (but at least 10 kB) at a time, there is no guarantee that the input will be left in any particular state when we reach the match limit.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I added the ugly else exit(0); as a quick fix for my use case.

There were some trouble either when piping or using multiple files, but I can't recall what problems exactly, sorry m(_ _)m

}
}
}

Expand Down Expand Up @@ -498,6 +507,7 @@ main(int argc, char **argv)
be_silent = 0;
tre_regaparams_default(&match_params);
match_params.max_cost = 0;
max_count = -1;

/* Parse command line options. */
while (1)
Expand Down Expand Up @@ -542,6 +552,10 @@ main(int argc, char **argv)
/* Only print files that contain matches. */
list_files = 1;
break;
case 'm':
/* stop after n selected lines */
max_count = atoi(optarg);
break;
case 'n':
/* Print record number of matching record. */
print_recnum = 1;
Expand Down Expand Up @@ -652,6 +666,10 @@ Copyright (c) 2001-2009 Ville Laurikari <vl@iki.fi>.\n"));
if (show_help)
tre_agrep_usage(0);

/* Fail without reading if count number is 0 */
if (max_count == 0)
return EXIT_FAILURE;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't use EXIT_SUCCESS or EXIT_FAILURE elsewhere, so we shouldn't use them here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then would return 1; be more appropriate?


if (color_option)
{
char *user_highlight = getenv("GREP_COLOR");
Expand Down