/* * Deal with duplicated lines in a file */ #include #include #include #include #include int fields = 0; int letters = 0; int linec = 0; char mode; int uniq; String *b1, *b2; Biobuf fin; Biobuf fout; String* gline(void); void pline(String *buf); int equal(String *b1, String *b2); char* skip(char *s); void main(int argc, char *argv[]) { int f; argv0 = argv[0]; 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((b1 = gline()) == nil) exits(0); for(;;) { linec++; if((b2 = gline()) == nil) { pline(b1); exits(0); } if(!equal(b1, b2)) { pline(b1); linec = 0; do { linec++; if((b1 = gline()) == nil) { pline(b2); exits(0); } } while(equal(b2, b1)); pline(b2); linec = 0; } } } String * gline(void) { char *t; if((t = Brdstr(&fin, '\n', 1)) == 0) return nil; return s_copy(t); } void pline(String *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", s_to_c(buf)); } int equal(String *d1, String *d2) { char c, *b1, *b2; b1 = s_to_c(d1); b2 = s_to_c(d2); if(s_len(d1) != s_len(d2)) return 0; 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; }