'cut' reposted
benjamin at uhmanoa.UUCP
benjamin at uhmanoa.UUCP
Fri Mar 13 05:32:02 AEST 1987
The cut source distributed by John Weald did not
seem to work right on our 4.3BSD. I've made some modifications
and allowed combination of range (-) and specifics (,) in the
argument list. If you have problems with the original posting,
replace with this below:
benjamin at uhmanoa.ICS.HAWAII.EDU
----------------------------- cut cut ----------------------------------
#! /bin/sh
#
# This is John Weald's 'cut' program which did not seem to
# work correctly. So I've made some modifications, seems okay
# right now, these are legal:
#
# cut -f3 -d' ' and cut -f1,3,2,4-6
#
#
# SHAR AND ENJOY !!!!!
#
PATH=/bin:/usr/bin:/usr/ucb; export PATH
echo shar: 'extracting "'cut.c'" '
if test -f 'cut.c' ; then
echo shar: will not over-write existing file "'cut.c'"
else
sed 's/^X//' >cut.c <<'@//E*O*F cut.c//'
X/*
X * This acts the same as SV cut(1), except that the list of numbers
X * does not have to be assending.
X *
X * John Weald
X */
X#include <stdio.h>
X#include <ctype.h>
X
X#define MAXLINE 1024 /* The max. length of a line */
X#define DEBUG 0
X
Xextern void exit();
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X extern char *optarg;
X extern int optind;
X
X static int fields[MAXLINE];/* The field markers. True if this field */
X /* is to be cut, False otherwise */
X FILE *fp; /* All the input files or stdin */
X char buf[MAXLINE]; /* The input buffer */
X int c; /* The command line option */
X int err = 0; /* True if error in command line */
X int fflag = 0; /* True if -f on command line */
X int cflag = 0; /* True if -c on command line */
X int suppress = 0; /* Suppress lines with no delimitor */
X char fs = '\t'; /* The field separator */
X
X
X while ((c = getopt(argc, argv, "f:d:c:s")) != EOF)
X {
X switch (c)
X {
X case 'f':
X /* By Field */
X list(fields, optarg);
X fflag++;
X if (cflag)
X err++;
X break;
X
X case 'c':
X /* By character */
X list(fields, optarg);
X /* Implied suppress */
X suppress++;
X cflag++;
X if (fflag)
X err++;
X break;
X
X case 'd':
X /* A new field spererator */
X fs = *optarg;
X break;
X
X case 's':
X suppress++;
X break;
X
X default:
X prusage();
X }
X }
X
X if (!cflag && !fflag)
X {
X fprintf(stderr, "Must have one of -f or -c\n");
X err++;
X }
X if (err)
X prusage();
X
X
X /*
X * Loop on all the files.
X */
X do {
X if (optind == argc)
X fp = stdin;
X else if ((fp = fopen(argv[optind], "r")) == (FILE *)NULL)
X {
X fprintf(stderr, "Failed to open file %s\n",
X argv[optind]);
X exit(1);
X }
X
X /*
X * Loop on all lines in the file.
X */
X while (fgets(buf, sizeof(buf), fp) != (char *)NULL)
X {
X cut(buf, fields, fs, suppress, cflag);
X }
X (void)fclose(fp);
X } while (++optind < argc);
X
X exit(0);
X/* NOTREACHED */
X}
X
X/*
X * Cut the line. This handles both character and field cutting.
X * For character cutting the f array gives character positions, for
X * fields it gives the field number. It must be indexed by either the
X * character number or the field number.
X */
Xcut(in, f, fs, sup, c_or_f)
Xregister char *in; /* The input line */
Xint f[]; /* The field cutting flags */
Xchar fs; /* The field seperator */
Xint sup; /* Suppress lines with no-delimitor? */
Xint c_or_f; /* Cut by char. (true), or field (false)*/
X{
X char obuf[MAXLINE]; /* Output buffer */
X register char *optr = obuf;
X register int i; /* Character count */
X register int fld; /* The field count */
X char *instart = in; /* To print lines with no delimiters */
X
X if (DEBUG) printf("c_or_f=%d\n",c_or_f);
X for (fld = 0, i = 0; i < MAXLINE; i++)
X {
X if (*in == '\n')
X {
X /* End of the line */
X
X *optr = '\0';
X /* Any thing to cut? */
X if (optr != obuf)
X {
X /* Get ride of trailing seperator */
X if (*(optr - 1) == fs)
X *(optr - 1) = '\0';
X puts(obuf);
X }
X else if (!sup)
X printf(instart);
X return;
X }
X if (DEBUG) printf("%d",f[c_or_f ? i : fld]);
X if (f[c_or_f ? i : fld])
X {
X *optr++ = *in;
X }
X
X /* End of field? */
X if (*in++ == fs)
X fld++;
X }
X
X fprintf(stderr, "Line too long, maximum length is %d\n", MAXLINE);
X exit(1);
X}
X
X/*
X * Parse the list argument. The format is:
X * n,n
X * where n is either a number or a range of numbers in the format
X * m-l
X * m or l may be absent, indicating the start or end of the lines respectivly.
X * Numbers must be in increasing order for m-l format, but not for n,n.
X * Field numbers start at 1, but index into fields array starts at 0.
X *
X */
Xlist(f, l)
Xint f[]; /* The fields */
Xchar *l; /* The list */
X{
X int range = 0; /* True if m-l format */
X int low, high; /* the low and high numbers in a m-l pair*/
X int noop,i;
X
X low = high = 0; noop = 1;
X
X while (1)
X {
X switch(*l)
X {
X case '\0':
X if (low > 0 && noop) f[low-1]++;
X return;
X
X case ',':
X if (noop) noop--;
X l++;
X if (!range) f[low-1]++;
X else {
X if (isdigit( (int)*l ))
X {
X f[ (low=atoi(l))-1 ]++;
X while(isdigit( (int)*l ) ) l++;
X }
X }
X range = 0;
X low = 1;
X break;
X
X case '-':
X l++;
X if (noop) noop--;
X range++;
X /* Is it m-<nothing> */
X if (isdigit((int)*l))
X {
X high = atoi(l);
X /* Skip the digits */
X while (isdigit((int) *l))
X l++;
X }
X else
X high = MAXLINE;
X
X /* Is the range the correct way around? */
X if (low > high)
X {
X fprintf(stderr, "Bad c/f list: %d > %d\n",
X low, high);
X exit(1);
X }
X /* Set the field flags for the range */
X for(i = low - 1; i < high; i++)
X f[i]++;
X break;
X
X default:
X /* either a number or an error */
X if (!isdigit((int) *l))
X {
X fprintf(stderr, "Bad c/f list at %s\n", l);
X exit(1);
X }
X low = atoi(l);
X if (low == 0)
X {
X fprintf(stderr, "Fields start at 1 not 0\n");
X exit(1);
X }
X /* Skip the digits */
X while (isdigit((int) *l))
X l++;
X break;
X }
X }
X}
X
Xprusage()
X{
X fprintf(stderr, "cut [-d<delimitor>] [-s] -c<list>|-f<list> [files]\n");
X exit(1);
X}
@//E*O*F cut.c//
echo "end of shar"
fi
exit 0
More information about the Comp.sources.unix
mailing list