field revisited
Bill Silvert
silvert at dalcs.UUCP
Thu Jul 25 12:59:08 AEST 1985
Here is a reposting of Steve Bourne's field program from his book. I
have made a number of enhancements (mainly a changeable field separator)
and added an expanded version of his manual entry. Also included are
two sample programs, a primitive implementation of finger for those of
us without the real thing, and a program to check for changes to the
password file (field skips the password itself, so only substantive
changes are noted).
This is similar to cut, found on Ver. III and V, but can be used to
change the order of fields which cut doesn't. I use field a lot on
tab-separated data files.
-----cut here-----cut here-----cut here-----cut here-----
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# field.1L
# field.c
# finger
# checkp
# This archive created: Wed Jul 24 07:51:37 1985
# By: Bill Silvert (Marine Ecology Lab, Dartmouth, N. S., Canada)
export PATH; PATH=/bin:$PATH
if test -f 'field.1L'
then
echo shar: will not over-write existing file "'field.1L'"
else
cat << \SHAR_EOF > 'field.1L'
.TH FIELD 1L
.SH NAME
field \- select fields or columns from a file
.SH SYNOPSIS
.B field
[-tc]
[-Tc]
[ n ] ...
.SH DESCRIPTION
The
.I 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.
.PP
The default delimiter is a tab.
This can be changed to character
.I c
with the option -t\c
.I c .
If the form -T\c
.I c
is used, the delimiter
.I c
is used on input, but the output is still separated by tabs.
.SH EXAMPLE
The following command extracts the login names, user and group numbers
from the password file:
.PP
field -t: 1 3 4 </etc/passwd
.SH SEE ALSO
.I Cut ,
which is available on System V.
There is a version of
.I cut
on this system, but no manual entry yet.
.SH BUGS
The number of input or output fields may not exceed 256 and
the maximum line length is 4096 characters.
.SH AUTHORS
Taken from "The Unix System" by S. R. Bourne.
Modifications by William Silvert.
SHAR_EOF
fi # end of overwriting check
if test -f 'field.c'
then
echo shar: will not over-write existing file "'field.c'"
else
cat << \SHAR_EOF > 'field.c'
/* field utility, from Bourne pp.228-9 */
#include <stdio.h>
static char SCCSID[] = "<@(#)field.c 1.11, 85/07/23>";
#define MAXF 256
#define MAXL 4096
#define IFS '\t' /* Field separator is tab on input, */
#define OFS '\t' /* and on output. */
int fv[MAXF];
int nf;
int mf;
char *fp[MAXF];
char L[MAXL];
main(argc,argv)
int argc;
char *argv[];
{
register char *cp;
register char **ap;
register int c;
int f;
char opt, fs, ifs=IFS, ofs=OFS;
while (argc>1) {
if(sscanf(argv[1], "-%c%c", &opt, &fs) == 2) {
switch(opt) {
case 't': /* change both field separators */
ofs = fs;
case 'T': /* change only ifs */
ifs = fs;
break;
default:
printf("usage: %s [-tc] [ n ] ...\n", argv[0]);
return(2);
}
}
else if(sscanf(argv[1], "%d", &fv[nf++]) != 1) {
printf("usage: %s [-tc] [ n ] ...\n", argv[0]);
return(2);
}
argc--; argv++;
}
/* read and copy input */
nf--;
cp = L;
ap = fp;
*ap++ = cp;
while(1){
c = getc(stdin);
if(c=='\n' || c== EOF) {
int fc;
if(cp==L && c==EOF) break;
*cp++ = 0;
mf = ap-fp;
/* print this line */
for(fc = 0; fc <= nf; fc++){
putf(fv[fc]-1);
if(fc != nf) putchar(ofs);
}
if(c == EOF) break;
putchar('\n');
cp = L;
ap = fp;
*ap++ = cp;
}
else if(c == ifs) {
*cp++ = 0;
*ap++ = cp;
}
else *cp++ = c;
}
return(0);
}
/* output field n from current line */
putf(n)
{
register char *cp = fp[n];
register char c;
if(n<0 || n>=mf) return;
while (c = *cp++) putchar(c);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'finger'
then
echo shar: will not over-write existing file "'finger'"
else
cat << \SHAR_EOF > 'finger'
: Silvert variant of finger -- use -a for all info
FIELD="field -t: 1 3 4 5 6"
case $# in
0) field -T: 1 5 < /etc/passwd ;;
*) for i
do case $i in
-a) FIELD="cat -v" ;;
-*) echo "$0: unknown flag $i" ; exit ;;
*) grep "^$i:" /etc/passwd | $FIELD ;;
esac
done ;;
esac
SHAR_EOF
chmod +x 'finger'
fi # end of overwriting check
if test -f 'checkp'
then
echo shar: will not over-write existing file "'checkp'"
else
cat << \SHAR_EOF > 'checkp'
#! /bin/sh
# check /etc/passwd for changes other than new passwords
PATH=/usr/new:/usr/local:/usr/bin:/bin
PASSWD=/etc/passwd
SECURE=/usr/adm/security
STOP=$SECURE/passwd
TEMP=/tmp/pass$$
DIFF=/tmp/diff$$
trap '/bin/rm -f $TEMP $DIFF;exit' 0 1 2 3 15
< $PASSWD field -t: 1 3 4 5 6 7 > $TEMP
diff $TEMP $STOP > $DIFF
if test -s $DIFF
then echo "Subject: Changes to /etc/passwd" > $TEMP
cat $TEMP $DIFF | mail root
exit 1
else
exit 0
fi
SHAR_EOF
chmod +x 'checkp'
fi # end of overwriting check
# End of shell archive
exit 0
--
Bill Silvert
Marine Ecology Lab.
Dartmouth, NS
dalcs!silvert
dalcs!biomel!bill
More information about the Comp.sources.unix
mailing list