diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/uniq.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/uniq.c')
-rwxr-xr-x | sys/src/cmd/uniq.c | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/sys/src/cmd/uniq.c b/sys/src/cmd/uniq.c new file mode 100755 index 000000000..1744dba03 --- /dev/null +++ b/sys/src/cmd/uniq.c @@ -0,0 +1,165 @@ +/* + * Deal with duplicated lines in a file + */ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <ctype.h> + +#define SIZE 8000 + +int fields = 0; +int letters = 0; +int linec = 0; +char mode; +int uniq; +char *b1, *b2; +long bsize; +Biobuf fin; +Biobuf fout; + +int gline(char *buf); +void pline(char *buf); +int equal(char *b1, char *b2); +char* skip(char *s); + +void +main(int argc, char *argv[]) +{ + int f; + + argv0 = argv[0]; + bsize = SIZE; + b1 = malloc(bsize); + b2 = malloc(bsize); + f = 0; + while(argc > 1) { + if(*argv[1] == '-') { + if(isdigit(argv[1][1])) + fields = atoi(&argv[1][1]); + else + mode = argv[1][1]; + argc--; + argv++; + continue; + } + if(*argv[1] == '+') { + letters = atoi(&argv[1][1]); + argc--; + argv++; + continue; + } + f = open(argv[1], 0); + if(f < 0) + sysfatal("cannot open %s", argv[1]); + break; + } + if(argc > 2) + sysfatal("unexpected argument %s", argv[2]); + Binit(&fin, f, OREAD); + Binit(&fout, 1, OWRITE); + + if(gline(b1)) + exits(0); + for(;;) { + linec++; + if(gline(b2)) { + pline(b1); + exits(0); + } + if(!equal(b1, b2)) { + pline(b1); + linec = 0; + do { + linec++; + if(gline(b1)) { + pline(b2); + exits(0); + } + } while(equal(b2, b1)); + pline(b2); + linec = 0; + } + } +} + +int +gline(char *buf) +{ + int len; + char *p; + + p = Brdline(&fin, '\n'); + if(p == 0) + return 1; + len = Blinelen(&fin); + if(len >= bsize-1) + sysfatal("line too long"); + memmove(buf, p, len); + buf[len-1] = 0; + return 0; +} + +void +pline(char *buf) +{ + switch(mode) { + + case 'u': + if(uniq) { + uniq = 0; + return; + } + break; + + case 'd': + if(uniq) + break; + return; + + case 'c': + Bprint(&fout, "%4d ", linec); + } + uniq = 0; + Bprint(&fout, "%s\n", buf); +} + +int +equal(char *b1, char *b2) +{ + char c; + + if(fields || letters) { + b1 = skip(b1); + b2 = skip(b2); + } + for(;;) { + c = *b1++; + if(c != *b2++) { + if(c == 0 && mode == 's') + return 1; + return 0; + } + if(c == 0) { + uniq++; + return 1; + } + } +} + +char* +skip(char *s) +{ + int nf, nl; + + nf = nl = 0; + while(nf++ < fields) { + while(*s == ' ' || *s == '\t') + s++; + while(!(*s == ' ' || *s == '\t' || *s == 0) ) + s++; + } + while(nl++ < letters && *s != 0) + s++; + return s; +} |