diff --git a/doc/agrep.1.in b/doc/agrep.1.in index 81d3beb..49cae36 100644 --- a/doc/agrep.1.in +++ b/doc/agrep.1.in @@ -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. diff --git a/src/agrep.c b/src/agrep.c index c3700b5..9f98c9e 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,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. */ @@ -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" */ + } } } @@ -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) @@ -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; @@ -652,6 +666,10 @@ Copyright (c) 2001-2009 Ville Laurikari .\n")); if (show_help) tre_agrep_usage(0); + /* Fail without reading if count number is 0 */ + if (max_count == 0) + return EXIT_FAILURE; + if (color_option) { char *user_highlight = getenv("GREP_COLOR");