benjamin@uhmanoa.UUCP (03/12/87)
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@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