.\" 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.
.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
*
* @(#) 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>
static int fflag;
static int nflag;
static int sflag;
+static int wflag;
static size_t autostart, autostop, maxval;
static char * positions;
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);
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);
case 'n':
nflag = 1;
break;
+ case 'w':
+ wflag = 1;
+ break;
case '?':
default:
usage();
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();
}
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') {
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)
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]);
(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);
}