From 16b0a807afb59da4d0a53fb2b27e59f5ade074ad Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Sat, 19 May 2001 07:55:43 +0000 Subject: Support new modes for uniq's --all-repeated option. The default behavior is unchanged. Include argmatch.h. (usage): Update. (check_file): Implement it. (main): Handle new, optional arguments. Patch by Padraig Brady. --- src/uniq.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/uniq.c b/src/uniq.c index 1c5bd39e0..abf87d5c1 100644 --- a/src/uniq.c +++ b/src/uniq.c @@ -25,6 +25,7 @@ #include "system.h" #include "closeout.h" +#include "argmatch.h" #include "linebuffer.h" #include "error.h" #include "xstrtol.h" @@ -81,11 +82,31 @@ static enum output_mode mode; /* If nonzero, ignore case when comparing. */ static int ignore_case; +enum delimit_method +{ + delimit_none, /* --all-repeated[=none] No delimiters output. */ + delimit_all, /* --all-repeated=all Delimiter precedes all groups. */ + delimit_minimum, /* --all-repeated=minimum Delimit all groups. */ +}; + +static char const *const delimit_method_string[] = +{ + "none", "all", "minimum", 0 +}; + +static enum delimit_method const delimit_method_map[] = +{ + delimit_none, delimit_all, delimit_minimum, +}; + +/* Select whether/how to delimit groups of duplicate lines. */ +static enum delimit_method delimit_groups; + static struct option const longopts[] = { {"count", no_argument, NULL, 'c'}, {"repeated", no_argument, NULL, 'd'}, - {"all-repeated", no_argument, NULL, 'D'}, + {"all-repeated", optional_argument, NULL, 'D'}, {"ignore-case", no_argument, NULL, 'i'}, {"unique", no_argument, NULL, 'u'}, {"skip-fields", required_argument, NULL, 'f'}, @@ -114,7 +135,9 @@ standard input), writing to OUTPUT (or standard output).\n\ \n\ -c, --count prefix lines by the number of occurrences\n\ -d, --repeated only print duplicate lines\n\ - -D, --all-repeated print all duplicate lines\n\ + -D, --all-repeated[=delimit-method] print all duplicate lines\n\ + delimit-method={all,minimum,none(default)}\n\ + Delimiting is done with blank lines.\n\ -f, --skip-fields=N avoid comparing the first N fields\n\ -i, --ignore-case ignore differences in case when comparing\n\ -s, --skip-chars=N avoid comparing the first N characters\n\ @@ -276,6 +299,7 @@ check_file (const char *infile, const char *outfile) char *prevfield; size_t prevlen; int match_count = 0; + int first_delimiter = 1; if (readline (prevline, istream) == 0) goto closefiles; @@ -296,6 +320,22 @@ check_file (const char *infile, const char *outfile) if (match) ++match_count; + if (mode == output_all_repeated && delimit_groups != delimit_none) + { + if (!match) + { + if (match_count) /* a previous match */ + first_delimiter = 0; /* Only used when delimit_minimum */ + } + else if (match_count == 1) + { + if ((delimit_groups == delimit_all) + || (delimit_groups == delimit_minimum + && !first_delimiter)) + putc ('\n', ostream); + } + } + if (!match || mode == output_all_repeated) { writeline (prevline, ostream, match_count); @@ -341,6 +381,7 @@ main (int argc, char **argv) check_chars = 0; mode = output_all; countmode = count_none; + delimit_groups = delimit_none; while ((optc = getopt_long (argc, argv, "0123456789cdDf:is:uw:", longopts, NULL)) != -1) @@ -373,6 +414,12 @@ main (int argc, char **argv) case 'D': mode = output_all_repeated; + if (optarg == NULL) + delimit_groups = delimit_none; + else + delimit_groups = XARGMATCH ("--all-repeated", optarg, + delimit_method_string, + delimit_method_map); break; case 'f': /* Like '-#'. */ -- cgit v1.2.3-54-g00ecf