/* * field [-tc] [-ic] [n] * * field utility, originally from Bourne pp.228-9. Distributed on * USENET, July 1985. Rewritten. */ /*)BUILD $(TKBOPTIONS) = { TASK = ...FLD } */ #ifdef DOCUMENTATION title field Select Fields or Columns from a File index Select fields or columns from a file synopsis field [-tc] [-ic] [ n ] ... description The field command copies selected, delimiter-separated fields from the standard input to the standard output. Fields are numbered from 1 and a field may be requested more than once. The default delimiter is a tab. This can be changed to character c with the option -tc. If the form -ic is used, the delimiter c is used on input, but the output is still separated by tabs. You can also specify both separators, but they must be in the order listed above: field -t/ -i= sets the output separator to '/' and the input separator to '='. example The following command extracts the login names, user and group numbers from a Unix password file: field -t: 1 3 4 #ifdef vms #include #include #define IO_SUCCESS (SS$_NORMAL | STS$M_INHIB_MSG) #define IO_ERROR SS$_ABORT #endif /* * Note: IO_SUCCESS and IO_ERROR are defined in the Decus C stdio.h file */ #ifndef IO_SUCCESS #define IO_SUCCESS 0 #endif #ifndef IO_ERROR #define IO_ERROR 1 #endif #define MAXF 256 #define MAXL 4096 #define IFS '\t' /* Default ffield separator is tab on input */ #define OFS '\t' /* and on output, too. */ int field[MAXF]; /* Field number to output (for reordering) */ int nfields = 0; /* field[0 .. nfields - 1] are active */ int linefields; /* Number of fields on this line */ char *fieldp[MAXF]; /* Points to first byte of this field */ char line[MAXL]; char insep = IFS; /* Input field separator */ char outsep = OFS; /* Output field separator */ main(argc,argv) int argc; char *argv[]; { register char *lp; /* Curr. pos on input line */ register char **fp; /* Current field (->fieldp[i]) */ register int c; int fcount; char opt, fs; #ifdef vms argc = getredirection(argc, argv); #endif while (argc > 1) { if (sscanf(argv[1], "-%c%c", &opt, &fs) == 2) { switch (opt) { case 't': /* change both field separators */ outsep = fs; case 'i': /* change only input separator */ insep = fs; break; default: goto usage; } } else if (sscanf(argv[1], "%d", &field[nfields++]) != 1) { usage: printf("usage: %s [-tc] [ n ] ...\n", argv[0]); exit(IO_ERROR); } argc--; argv++; } while (!feof(stdin)) { lp = line; fp = fieldp; *fp++ = lp; /* First field */ while ((c = getchar()) != '\n' && c != EOF) { if (c == insep) { *fp++ = lp; /* Start of next field */ } else { *lp++ = c; /* Store char in field */ } } if (lp == line && c == EOF) break; *fp = lp; /* Remember last's end */ linefields = fp - fieldp; /* Fields on this line */ for (fcount = 0; fcount < nfields; fcount++) { outputfield(field[fcount] - 1); /* Output nth field */ if (fcount != (nfields - 1)) /* Maybe separator, too */ putchar(outsep); } if (c == '\n') putchar('\n'); } return (IO_SUCCESS); } outputfield(n) int n; /* * output field n from current line */ { register char *lp; register char *ep; if (n < 0 || n >= linefields) return; lp = fieldp[n]; ep = fieldp[n + 1]; while (lp < ep) putchar(*lp++); }