cut(1): Add back -w (split on whitespace functionality).
authorSascha Wildner <saw@online.de>
Thu, 9 Aug 2012 00:56:25 +0000 (02:56 +0200)
committerSascha Wildner <saw@online.de>
Thu, 9 Aug 2012 00:56:25 +0000 (02:56 +0200)
Reported-by: Tim Darby <t+dfbsd@timdarby.net>
Dragonfly-bug: <http://bugs.dragonflybsd.org/issues/2385>

usr.bin/cut/cut.1
usr.bin/cut/cut.c

index 42e10a3..fbbdbd8 100644 (file)
@@ -29,9 +29,9 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     @(#)cut.1      8.1 (Berkeley) 6/6/93
-.\" $FreeBSD$
+.\" $FreeBSD: src/usr.bin/cut/cut.1,v 1.36 2012/06/11 03:10:15 kevlo Exp $
 .\"
-.Dd December 21, 2006
+.Dd August 8, 2012
 .Dt CUT 1
 .Os
 .Sh NAME
 .Op Ar
 .Nm
 .Fl f Ar list
-.Op Fl d Ar delim
+.Op Fl w | Fl d Ar delim
 .Op Fl s
 .Op Ar
 .Sh DESCRIPTION
 The
 .Nm
 utility cuts out selected portions of each line (as specified by
-.Ar list  )
+.Ar list )
 from each
 .Ar file
 and writes them to the standard output.
@@ -119,6 +119,9 @@ that form the character are selected.
 .It Fl s
 Suppress lines with no field delimiter characters.
 Unless specified, lines with no delimiters are passed through unmodified.
+.It Fl w
+Use whitespace (spaces and tabs) as the delimiter.
+Consecutive spaces and tabs count as one single field separator.
 .El
 .Sh ENVIRONMENT
 The
index 1da999d..ea29840 100644 (file)
@@ -31,7 +31,7 @@
  *
  * @(#) Copyright (c) 1989, 1993 The Regents of the University of California.  All rights reserved.
  * @(#)cut.c   8.3 (Berkeley) 5/4/95
- * $FreeBSD: src/usr.bin/cut/cut.c,v 1.9.2.3 2001/07/30 09:59:16 dd Exp $
+ * $FreeBSD: src/usr.bin/cut/cut.c,v 1.33 2012/06/11 03:02:40 kevlo Exp $
  */
 
 #include <ctype.h>
@@ -53,6 +53,7 @@ static int    dflag;
 static int     fflag;
 static int     nflag;
 static int     sflag;
+static int     wflag;
 
 static size_t  autostart, autostop, maxval;
 static char *  positions;
@@ -62,6 +63,7 @@ static int    b_n_cut(FILE *, const char *);
 static int     c_cut(FILE *, const char *);
 static int     f_cut(FILE *, const char *);
 static void    get_list(char *);
+static int     is_delim(int);
 static void    needpos(size_t);
 static void    usage(void);
 
@@ -79,7 +81,7 @@ main(int argc, char *argv[])
        dchar = '\t';                   /* default delimiter is \t */
        strcpy(dcharmb, "\t");
 
-       while ((ch = getopt(argc, argv, "b:c:d:f:sn")) != -1)
+       while ((ch = getopt(argc, argv, "b:c:d:f:snw")) != -1)
                switch(ch) {
                case 'b':
                        get_list(optarg);
@@ -106,6 +108,9 @@ main(int argc, char *argv[])
                case 'n':
                        nflag = 1;
                        break;
+               case 'w':
+                       wflag = 1;
+                       break;
                case '?':
                default:
                        usage();
@@ -114,9 +119,9 @@ main(int argc, char *argv[])
        argv += optind;
 
        if (fflag) {
-               if (bflag || cflag || nflag)
+               if (bflag || cflag || nflag || (wflag && dflag))
                        usage();
-       } else if (!(bflag || cflag) || dflag || sflag)
+       } else if (!(bflag || cflag) || dflag || sflag || wflag)
                        usage();
        else if (!bflag && nflag)
                usage();
@@ -354,18 +359,30 @@ out:
 }
 
 static int
+is_delim(int ch)
+{
+       if (wflag) {
+               if (ch == ' ' || ch == '\t')
+                       return 1;
+       } else {
+               if (ch == dchar)
+                       return 1;
+       }
+       return 0;
+}
+
+static int
 f_cut(FILE *fp, const char *fname)
 {
        wchar_t ch;
        int field, i, isdelim;
        char *pos, *p;
-       wchar_t sep;
        int output;
        char *lbuf, *mlbuf;
        size_t clen, lbuflen, reallen;
 
        mlbuf = NULL;
-       for (sep = dchar; (lbuf = fgetln(fp, &lbuflen)) != NULL;) {
+       while ((lbuf = fgetln(fp, &lbuflen)) != NULL) {
                reallen = lbuflen;
                /* Assert EOL has a newline. */
                if (*(lbuf + lbuflen - 1) != '\n') {
@@ -389,7 +406,7 @@ f_cut(FILE *fp, const char *fname)
                        if (clen == 0)
                                clen = 1;
                        /* this should work if newline is delimiter */
-                       if (ch == sep)
+                       if (is_delim(ch))
                                isdelim = 1;
                        if (ch == '\n') {
                                if (!isdelim && !sflag)
@@ -416,8 +433,13 @@ f_cut(FILE *fp, const char *fname)
                                if (clen == 0)
                                        clen = 1;
                                p += clen;
-                               if (ch == '\n' || ch == sep)
+                               if (ch == '\n' || is_delim(ch)) {
+                                       /* compress whitespace */
+                                       if (wflag && ch != '\n')
+                                               while (is_delim(*p))
+                                                       p++;
                                        break;
+                               }
                                if (*pos)
                                        for (i = 0; i < (int)clen; i++)
                                                putchar(p[i - clen]);
@@ -447,6 +469,6 @@ usage(void)
        (void)fprintf(stderr, "%s\n%s\n%s\n",
                "usage: cut -b list [-n] [file ...]",
                "       cut -c list [file ...]",
-               "       cut -f list [-s] [-d delim] [file ...]");
+               "       cut -f list [-s] [-w | -d delim] [file ...]");
        exit(1);
 }