Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 22 Dec 2019 20:34:15 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r356025 - stable/12/usr.bin/uniq
Message-ID:  <201912222034.xBMKYFPH077485@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Sun Dec 22 20:34:15 2019
New Revision: 356025
URL: https://svnweb.freebsd.org/changeset/base/356025

Log:
  MFC r355777:
  
  Support --all-repeats in uniq(1) for compatibility with gnu coreutils.
  
  This adds a new -D/--all-repeats option to uniq(1), which outputs each copy
  of any repeated lines (as opposed to a single copy of a repeated line). You
  can specify a separator option to output a blank line before or after each
  group of repeated lines. This adds compatibility with the GNU coreutils
  version of uniq(1).
  
  This change also re-groups the -c, -d, -D, -u options in the usage display
  and man page to indicate that they are mutally exclusive of each other. This
  matches the posix/opengroup definition of uniq(1) command line args. Note
  that this change does NOT actually enforce the mutual exclusion in the code,
  for now, it simply documents that the arguments should be considered
  exclusive with each other.
  
  Differential Revision:	https://reviews.freebsd.org/D22262

Modified:
  stable/12/usr.bin/uniq/uniq.1
  stable/12/usr.bin/uniq/uniq.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/usr.bin/uniq/uniq.1
==============================================================================
--- stable/12/usr.bin/uniq/uniq.1	Sun Dec 22 20:06:08 2019	(r356024)
+++ stable/12/usr.bin/uniq/uniq.1	Sun Dec 22 20:34:15 2019	(r356025)
@@ -31,7 +31,7 @@
 .\"     From: @(#)uniq.1	8.1 (Berkeley) 6/6/93
 .\" $FreeBSD$
 .\"
-.Dd May 1, 2018
+.Dd December 15, 2019
 .Dt UNIQ 1
 .Os
 .Sh NAME
@@ -39,8 +39,7 @@
 .Nd report or filter out repeated lines in a file
 .Sh SYNOPSIS
 .Nm
-.Op Fl c
-.Op Fl d | Fl u
+.Op Fl c | Fl d | Fl D | Fl u
 .Op Fl i
 .Op Fl f Ar num
 .Op Fl s Ar chars
@@ -75,7 +74,24 @@ The following options are available:
 Precede each output line with the count of the number of times the line
 occurred in the input, followed by a single space.
 .It Fl d , Fl -repeated
-Only output lines that are repeated in the input.
+Output a single copy of each line that is repeated in the input.
+.It Fl D , Fl -all-repeated Op Ar septype
+Output all lines that are repeated (like
+.Fl d ,
+but each copy of the repeated line is written).
+The optional
+.Ar septype
+argument controls how to separate groups of repeated lines in the output;
+it must be one of the following values:
+.Pp
+.Bl -tag -compact -width separate
+.It none
+Do not separate groups of lines (this is the default).
+.It prepend
+Output an empty line before each group of lines.
+.It separate
+Output an empty line after each group of lines.
+.El
 .It Fl f Ar num , Fl -skip-fields Ar num
 Ignore the first
 .Ar num

Modified: stable/12/usr.bin/uniq/uniq.c
==============================================================================
--- stable/12/usr.bin/uniq/uniq.c	Sun Dec 22 20:06:08 2019	(r356024)
+++ stable/12/usr.bin/uniq/uniq.c	Sun Dec 22 20:34:15 2019	(r356025)
@@ -65,11 +65,18 @@ static const char rcsid[] =
 #include <wchar.h>
 #include <wctype.h>
 
-static int cflag, dflag, uflag, iflag;
+static int Dflag, cflag, dflag, uflag, iflag;
 static int numchars, numfields, repeats;
 
+/* Dflag values */
+#define	DF_NONE		0
+#define	DF_NOSEP	1
+#define	DF_PRESEP	2
+#define	DF_POSTSEP	3
+
 static const struct option long_opts[] =
 {
+	{"all-repeated",optional_argument,	NULL, 'D'},
 	{"count",	no_argument,		NULL, 'c'},
 	{"repeated",	no_argument,		NULL, 'd'},
 	{"skip-fields",	required_argument,	NULL, 'f'},
@@ -101,9 +108,19 @@ main (int argc, char *argv[])
 	(void) setlocale(LC_ALL, "");
 
 	obsolete(argv);
-	while ((ch = getopt_long(argc, argv, "+cdif:s:u", long_opts,
+	while ((ch = getopt_long(argc, argv, "+D::cdif:s:u", long_opts,
 	    NULL)) != -1)
 		switch (ch) {
+		case 'D':
+			if (optarg == NULL || strcasecmp(optarg, "none") == 0)
+				Dflag = DF_NOSEP;
+			else if (strcasecmp(optarg, "prepend") == 0)
+				Dflag = DF_PRESEP;
+			else if (strcasecmp(optarg, "separate") == 0)
+				Dflag = DF_POSTSEP;
+			else
+				usage();
+			break;
 		case 'c':
 			cflag = 1;
 			break;
@@ -194,7 +211,10 @@ main (int argc, char *argv[])
 
 		if (comp) {
 			/* If different, print; set previous to new value. */
-			show(ofp, prevline);
+			if (Dflag == DF_POSTSEP && repeats > 0)
+				fputc('\n', ofp);
+			if (!Dflag)
+				show(ofp, prevline);
 			p = prevline;
 			b1 = prevbuflen;
 			prevline = thisline;
@@ -206,12 +226,22 @@ main (int argc, char *argv[])
 			thisbuflen = b1;
 			tthis = NULL;
 			repeats = 0;
-		} else
+		} else {
+			if (Dflag) {
+				if (repeats == 0) {
+					if (Dflag == DF_PRESEP)
+						fputc('\n', ofp);
+					show(ofp, prevline);
+				}
+				show(ofp, thisline);
+			}
 			++repeats;
+		}
 	}
 	if (ferror(ifp))
 		err(1, "%s", ifn);
-	show(ofp, prevline);
+	if (!Dflag)
+		show(ofp, prevline);
 	exit(0);
 }
 
@@ -276,7 +306,7 @@ static void
 show(FILE *ofp, const char *str)
 {
 
-	if ((dflag && repeats == 0) || (uflag && repeats > 0))
+	if ((!Dflag && dflag && repeats == 0) || (uflag && repeats > 0))
 		return;
 	if (cflag)
 		(void)fprintf(ofp, "%4d %s", repeats + 1, str);
@@ -343,6 +373,6 @@ static void
 usage(void)
 {
 	(void)fprintf(stderr,
-"usage: uniq [-c] [-d | -u] [-i] [-f fields] [-s chars] [input [output]]\n");
+"usage: uniq [-c | -d | -D | -u] [-i] [-f fields] [-s chars] [input [output]]\n");
 	exit(1);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201912222034.xBMKYFPH077485>