SQ79%liverpool.ac.uk@nsfnet-relay.ac.uk (Mark Powell) (09/14/89)
Here is an implementation of cut and paste for minix, written by a friend of mine, who doesn't have USENET access. He has a Pc and I have an ST. It compiles okay on both machines. Not sure about libraries, but both me and my friend are using the PC-1.4a libraries. Enjoy. A very useful program that minix has been missing out on. Should make shell scripts easier! Mark Powell P.S. Yes I know PC1.4a already has paste(1), don't ask me why he wrote his own! ARPA sq79%liv.ac.uk@nsfnet-relay.ac.uk UUCP ...!mcvax!ukc!liv.ac.uk!sq79 ----------------------------Cut here------------------------------------ echo x - readme sed '/^X/s///' > readme << '/' XHere is cut(1) and paste(1) for MINIX. Cut for those not familiar Xwith it is a useful little tool used for stripping out columns Xand fields from lines of ascii files. (particularly useful Xfor manipulating files such as /etc/passwd). Included is a X(slightly thrown together) MAN file. Paste being the opposite. XPlease pass it on and enjoy. X XP.S. This is my first addition to the newsgroup and I would like Xto hear from anyone who has been developing software specifically Xfor the AMSTRAD PC e.g. mouse driver ???? X XIf anyone is interested I have written fairly fast screen drivers Xto support software mode 6 (640x200 2 colours). I have Xtwo drivers, named /dev/screen0 and 1. When writing to screen0 Xdata appears row by row with none of your crazy memory Xmapping hassle, and when writting to screen1 data appears Xcolumn by column. This allows both vertical and horizontal Xlines to be written at similarly fast speeds. I am also Xworking on a support library. X XDoes anybody know anything about optimum interleave factors Xfor hard disks under MINIX. Recently I changed the interleave Xfactor on my Western Digital Filecard (21meg) (which Xincidentally runs under MINIX with no trouble) from 4 to 10. XThis resulted in a near 3 times speed increase under DOS, but Xshowed minimal difference under MINIX. Is it possible to Xhave separate partitions with a different interleave factor? XIf so where can I get the necessary software to achieve this? X XAnyway Hope this is of interest to some of you. X XMike Holme. X X I can be contacted via my friends email address X X JANET sq79@uk.ac.liv <Mark Powell> X ARPA sq79%liv.ac.uk@nsfnet-relay.ac.uk X UUCP ...!mcvax!ukc!liv.ac.uk!sq79 X X or alternatively tel: 0925 754259 X X or 11, Bollin Drive, X Lymm, X Cheshire. X WA13 9QA X XCheers. X---------------------------------cut here--------------------------------------- / echo x - cut.c sed '/^X/s///' > cut.c << '/' X/* cut - extract columns from a file or stdin. Author: Michael J Holme X * X * Copyright 1989, Michael John Holme, All rights reserved. X * This code may be freely distributed, provided that this notice X * remains intact. X * X * V1.1: 6th September 1989 X * X * Bugs, criticisms, etc, X * c/o Mark Powell X * JANET sq79@uk.ac.liv X * ARPA sq79%liv.ac.uk@nsfnet-relay.ac.uk X * UUCP ...!mcvax!ukc!liv.ac.uk!sq79 X */ X X#include <stdio.h> X#include <ctype.h> X#include <string.h> X X#define MAX_FIELD 80 /* Pointers to the beginning of each field X are stored in columns[], if a line holds X more than MAX_FIELD columns the array X boundary is exceed. But unlikely at 80 */ Xchar *columns[MAX_FIELD]; X X#define MAX_ARGS 32 /* Maximum number of fields following X -f or -c switches */ Xint args[MAX_ARGS*2]; Xint num_args; X Xint mode; /* 0 = dump stdin to stdout, 1=-f, 2=-c */ Xint flagi; /* 1=-i, 0=no -i */ Xchar delim = '\t'; /* default delimiting character */ XFILE *fd; Xchar *name; Xchar line[BUFSIZ]; Xextern int errno; X Xvoid cuterror(err) Xint err; X{ Xstatic char *err_mes[] = { X "%s: syntax error\n", X "%s: position must be >0\n", X "%s: unknown option\n", X "%s: usage: cut [-f{args} [-i] [-d'x']]|[-c{args}] [filename [...]]\n", X "%s: line longer than BUFSIZ\n", X "%s: -d option not applicable\n", X "%s: -i option not applicable\n", X "%s: range must not decrease from left to right\n", X "%s: MAX_FIELD exceeded\n", X "%s: MAX_ARGS exceeded\n" X } ; X printf(err_mes[err-1], name); X exit(err); X} X X Xvoid get_args() X{ Xint i=0; Xint arg_ptr=0; Xint flag; X X num_args=0; X do X { X if(num_args==MAX_ARGS) cuterror(10); X if(!isdigit(line[i]) && line[i]!='-') cuterror(1); X X args[arg_ptr]=1; X args[arg_ptr+1]=BUFSIZ; X flag=1; X X while(line[i]!=',' && line[i]!=NULL) X { X if(isdigit(line[i])) X { X args[arg_ptr]=0; X while(isdigit(line[i])) X args[arg_ptr]=10*args[arg_ptr]+line[i++]-'0'; X if(!args[arg_ptr]) cuterror(2); X arg_ptr++; X } X if(line[i]=='-') X { X arg_ptr|=1; X i++; X flag=0; X } X } X if(flag && arg_ptr&1) args[arg_ptr]=args[arg_ptr-1]; X if(args[num_args*2] > args[num_args*2+1]) cuterror(8); X num_args++; X arg_ptr=num_args*2; X } X while(line[i++]); X} X X Xvoid cut() X{ Xint i, j, length, maxcol; X X while(fgets(line, BUFSIZ, fd)) X { X length=strlen(line)-1; X *(line+length)=NULL; X switch(mode) X { X case 0 : printf("%s", line); X break; X case 1 : maxcol=0; X columns[maxcol++]=line; X for(i=0; i<length; i++) X { X if(*(line+i)==delim) X { X *(line+i)=NULL; X if(maxcol==MAX_FIELD) cuterror(9); X columns[maxcol]=line+i+1; X while(*(line+i+1)==delim && flagi) X { X columns[maxcol]++; X i++; X } X maxcol++; X } X } X for(i=0; i<num_args; i++) X { X for(j=args[i*2]; j<=args[i*2+1]; j++) X if(j<=maxcol) X { X printf("%s", columns[j-1]); X if(i!=num_args-1 || j!=args[i*2+1]) X putchar(delim); X } X } X break; X case 2 : for(i=0; i<num_args; i++) X { X for(j=args[i*2];j<=(args[i*2+1]>length ? length : args[i*2+1]); j++) X putchar( *(line+j-1) ); X } X } X putchar('\n'); X } X} X X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ Xint flag; Xint i=1; X X name=argv[0]; X if(argc==1) cuterror(4); X X while(argv[i] != NULL && argv[i][0] == '-') X { X switch(argv[i][1]) X { X case 'd': if(mode==2) cuterror(6); X sprintf(line,"%.1s", &argv[i++][2]); X delim=line[0]; X break; X case 'f': sprintf(line, "%s", &argv[i++][2]); X mode=1; X get_args(); X break; X case 'c': sprintf(line, "%s", &argv[i++][2]); X mode=2; X get_args(); X break; X case 'i': if(mode==2) cuterror(7); X flagi=1; X i++; X break; X default : cuterror(3); X } X } X X if(i < argc) X if((fd=fopen(argv[i], "r")) == NULL) X { X printf("%s: couldn't open %s\n", name, argv[i]); X exit(errno); X } X else X { X cut(); X fclose(fd); X } X else X { X fd=stdin; X cut(); X } X exit(0); X} X / echo x - cut.1 sed '/^X/s///' > cut.1 << '/' XNAME X cut(1) - select fields or columns from line input X XSYNOPSIS X cut [[-i] [-d'x'] -f{args} [file ...] X cut [-c{args}] [file ...] X XDESCRIPTION X Cut copies the named ascii files ( or standard input ) to X standard output. In the process of copying, Cut extracts X specified columns. Columns may be specified by character X positions, from 1 to BUFMAX, or by field numbers. X Fields are groups of characters seperated from each other X by the field delimiting character. X X Field and character mode are mutually exclusive and specified X by the flags -f{args} and -c{args} respectively. X X {args} takes the form of a comma seperated list of ranges. X e.g. 1-5,8- extract all but 6 and 7. X -5 extract the first five. X 1,3,2 extract one, three and two (in X that order). X X -d'x' X X This is used to changes the field delimiting character X from the default [tab] to char(x). X NOTE: this is only of use with the -f option. X X -i X X Informs cut to ignore null fields ( e.g. consecutive X spaces are treated as one ) X NOTE: again, only of use with -f X XEXAMPLES X X $ cut -d: -f1 /etc/passwd X root X uucp X mjh X bin X daemon X msp X $ cat >filex X Bert Fred Jim X Sally Hilary Margaret X [CNTL-D] X $ cut -d' ' -f2,1 filex X Fred Bert X Hilary Sally X $ for i in `cut -d: -f6 /etc/passwd` X > do X > echo User `basename $i`: `du -s $i | cut -f1` blocks X > done X User root: 500 blocks X User uucp: 80 blocks X etc... X $ cut -c-4,-3,-2,1 /etc/passwd X rootrooror X uucpuucuuu X mjh:mjhmjm X etc... X $ X ls -al | cut -d' ' -f4 -i X 1345 X 456 X 32223 X 456 X XAUTHOR X Michael J Holme. X XSEE ALSO X paste(1) X / echo x - paste.c sed '/^X/s///' > paste.c << '/' X/* paste - merge files vertically. Author: Michael J Holme X * X * Copyright 1989, Michael John Holme, All rights reserved. X * This code may be freely distributed, provided that this notice X * remains intact. X * X * V1.0: 6th September 1989 X * X * Bugs, criticisms, etc, X * c/o Mark Powell X * JANET sq79@uk.ac.liv X * ARPA sq79%liv.ac.uk@nsfnet-relay.ac.uk X * UUCP ...!mcvax!ukc!liv.ac.uk!sq79 X */ X X#include <stdio.h> X#include <limits.h> X Xchar delims[OPEN_MAX+1]; Xchar line[BUFSIZ]; Xchar *name; Xchar *malloc(); Xint numfiles=0; Xextern int errno; XFILE *fd[OPEN_MAX]; X X Xvoid pasteerr(err) Xint err; X{ Xstatic char *err_mes[] = { X "%s: usage: paste [-d\"string\"] file[...]", X "%s: unknown option\n", X "%s: too many open files\n" X } ; X printf(err_mes[err-1], name); X exit(err); X} X X Xvoid paste(void) X{ Xint i, j; Xint numopen; X X numopen=numfiles; X while(numopen) X { X for(i=0; i<numfiles; i++) X { X if(fd[i]) X { X if(fgets(line, BUFSIZ, fd[i])) X { X j=strlen(line); X *(line+j-1)=NULL; X printf("%s", line); X } X else X { X fclose(fd[i]); X fd[i]=0; X numopen--; X } X if(i!=numfiles-1) putchar(*(delims+i)); X } X } X putchar('\n'); X } X} X X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ Xint i, j; X X name=argv[0]; X if(argc==1) pasteerr(1); X X for(i=0; i<OPEN_MAX; i++) delims[i]='\t'; X X i=1; X if(argv[i][0] == '-') X { X switch(argv[i][1]) X { X case 'd': sprintf(delims,"%OPEN_MAX.s", &argv[i++][2]); X delims[strlen(delims)]='\t'; X break; X case 0 : fd[numfiles++]=stdin; X i++; X break; X default : pasteerr(2); X } X } X X while(i < argc) X { X if(numfiles==OPEN_MAX) pasteerr(3); X if((fd[numfiles++]=fopen(argv[i], "r")) == NULL) X { X printf("%s: couldn't open %s\n", name, argv[i]); X exit(errno); X } X i++; X } X paste(); X exit(0); X} X X / echo x - paste.1 sed '/^X/s///' > paste.1 << '/' XNAME X paste(1) - combine files vertically. X XSYNOPSIS X cut [-d"string"] [file ...] X XDESCRIPTION X Paste takes consecutive lines from each specified file and X combines them to form one line. The output is via standard X output and a tab is placed between each field one each X line. The -d"string" switch may be used to specify the X new field delimiting characters. X In fitting with other commands, a minus sign may be used X in place of a filename to specify standard input at that X point in the list. X XEXAMPLES X $ cat >filex X Bert X Fred X Jim X cat >filey X Sally X Hilary X Margaret X [CNTL-D] X $ paste filex filey X Bert Sally X Fred Hilary X Jim Margaret X $ paste -d":^!" filex filey filex filey X Bert:Sally^Bert!Sally X Fred:Hilary^Fred!Hilary X Jim:Margaret^Jim!Margaret X XAUTHOR X Michael J Holme. X XSEE ALSO X cut(1) X / echo x - hogs sed '/^X/s///' > hogs << '/' X# hogs: display block usage per user and spot the disk HOGS X# X# Written by M.J.Holme X Xfor i in `cut -d: -f6 /etc/passwd` Xdo X echo -n User `basename $i`: X blocks=`du -s $i | cut -f1` X echo -n " $blocks" X if ( test 512 -lt $blocks ) ; then X echo ' blocks (HOG)' X else echo ' blocks' X fi Xdone / chmod 755 hogs
fredriks@cbnewse.ATT.COM (lars.fredriksen) (01/13/90)
Hi! I tried to extract columns from a file, just as ast tried to do with cut, but I used the shell. Correct me if I am wrong, but it would seem to me that the following should work: while read COL1 COL2 COL3 ; do echo $COL2 $COL3 done Let say the script is called "extract", then you could do extract < listing > output or whatever you want to do.. The only hitch with this scheme is that the shell is broken. The documentation on the Bourne shell says that read reads a line from stdin, then assigning the first word to the first variable, second word to the second variable,.. rest of the line to the last variable. That means that if the listing file in the above example contained: 011090 45000 cu.c COL1 should be equal to 011090, COL2 = 45000, and COL3 = cu.c. With the minix shell this is what you get: COL1 = 011090, COL2 = " ", COL3 = 45000. We could work around this by using variables for the spaces too. That holds true for a file that has the same number of spaces between each column, but not if the file looks like the one following: 011090 4500 cu.c 011190 500 temp.out 011290 0 empty.out It is even possible to handle this, but it becomes a mess in a hurry. Another thing that the shell seems to do wrong(This has probably been pointed out already) is the following: FILES=`/bin/ls *.c` for i in $FILES ; do echo $i done The shell varible dosn't have the right format for this to work. If my memory server me right, only the last file will be echoed. I haven't tested this under 1.5.0 yet. PS. In regards to system V's version of cut; here is an extract from the man pages: -d char The character following -d is the field delimiter (-f option only). Default if tab. Space or other characters with special meaning to the shell must be quoted. -flist The list following -f is a list of fileds assumed to be separated by the delimiter character specified by the -d option;e.q., -f1,7 copies the first and seventh field only. Sincerely Lars Fredriksen