From 890b693163163149b6831922269ab22a175a019d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Wed, 4 Sep 2024 17:40:45 +0200 Subject: [PATCH] Add -m option to agrep. This behaves similarly to the equivalent option in GNU and BSD grep, i.e. stops processing each input as soon as the specified number of matches is reached. Fixes #93. --- doc/agrep.1.in | 8 ++++++++ src/agrep.c | 16 +++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/doc/agrep.1.in b/doc/agrep.1.in index 81d3beb..912cc37 100644 --- a/doc/agrep.1.in +++ b/doc/agrep.1.in @@ -128,6 +128,14 @@ Only print the name of each input file which contains at least one match, suppressing normal output. The scanning for each file will stop on the first match. .TP +.BI \-m " NUM" "\fR,\fP \-\^\-max\-count=" NUM +Stop processing each input file after +.I NUM +matching (or non-matching if +.B \-v +was specified) lines. +A negative value is interpreted as infinity, which is the default. +.TP .BR \-n ", " \-\^\-record\-number Prefix each output record with its sequence number in the input file. The number of the first record is 1. diff --git a/src/agrep.c b/src/agrep.c index 377dbd8..9d2d0c6 100644 --- a/src/agrep.c +++ b/src/agrep.c @@ -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; @@ -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'}, @@ -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\ @@ -185,6 +187,7 @@ 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 matching lines per input. */ static int list_files; /* List matching files. */ static int color_option; /* Highlight matches. */ static int print_position; /* Show start and end offsets for matches. */ @@ -449,6 +452,8 @@ tre_agrep_handle_file(const char *filename) printf("%.*s", record_len, record); } } + if (max_count > 0 && count >= max_count) + break; } } @@ -498,6 +503,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) @@ -542,6 +548,10 @@ main(int argc, char **argv) /* Only print files that contain matches. */ list_files = 1; break; + case 'm': + /* Stop after max_count matches. */ + max_count = atoi(optarg); + break; case 'n': /* Print record number of matching record. */ print_recnum = 1; @@ -652,6 +662,10 @@ Copyright (c) 2001-2009 Ville Laurikari .\n")); if (show_help) tre_agrep_usage(0); + /* Fail immediately if max_count is 0. */ + if (max_count == 0) + return EXIT_FAILURE; + if (color_option) { char *user_highlight = getenv("GREP_COLOR");