From f1fa2b8ec8c4ec676f75d70a29fbdeec4bef3a08 Mon Sep 17 00:00:00 2001 From: eadler Date: Sun, 16 Dec 2012 17:01:23 +0000 Subject: [PATCH] MFC r243320,r243474: Add 'w' flag to: Use whitespace (spaces and tabs) as the delimiter. Consecutive spaces and tabs count as one single field separator. Approved by: cperciva (implicit) git-svn-id: svn://svn.freebsd.org/base/stable/8@244305 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- usr.bin/cut/cut.1 | 7 +++++-- usr.bin/cut/cut.c | 38 ++++++++++++++++++++++++++++++-------- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/usr.bin/cut/cut.1 b/usr.bin/cut/cut.1 index 67ee36970..2c1c4ca0c 100644 --- a/usr.bin/cut/cut.1 +++ b/usr.bin/cut/cut.1 @@ -35,7 +35,7 @@ .\" @(#)cut.1 8.1 (Berkeley) 6/6/93 .\" $FreeBSD$ .\" -.Dd December 21, 2006 +.Dd August 8, 2012 .Dt CUT 1 .Os .Sh NAME @@ -51,7 +51,7 @@ .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 @@ -123,6 +123,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 diff --git a/usr.bin/cut/cut.c b/usr.bin/cut/cut.c index 74aa52a5e..d187c30fa 100644 --- a/usr.bin/cut/cut.c +++ b/usr.bin/cut/cut.c @@ -62,6 +62,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; @@ -71,6 +72,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(wchar_t); static void needpos(size_t); static void usage(void); @@ -88,7 +90,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); @@ -115,6 +117,9 @@ main(int argc, char *argv[]) case 'n': nflag = 1; break; + case 'w': + wflag = 1; + break; case '?': default: usage(); @@ -123,9 +128,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(); @@ -362,19 +367,31 @@ out: return (0); } +static int +is_delim(wchar_t 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') { @@ -398,7 +415,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) @@ -425,8 +442,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]); @@ -456,6 +478,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); } -- 2.45.0