1 /* uniq.c - report or filter out repeated lines in a file
3 * Copyright 2012 Georgi Chorbadzhiyski <georgi@unixsol.org>
5 * See http://opengroup.org/onlinepubs/9699919799/utilities/uniq.html
7 USE_UNIQ(NEWTOY(uniq, "f#s#w#zicdu", TOYFLAG_USR|TOYFLAG_BIN))
13 usage: uniq [-cduiz] [-w maxchars] [-f fields] [-s char] [input_file [output_file]]
15 Report or filter out repeated lines in a file
17 -c show counts before each line
18 -d show only lines that are repeated
19 -u show only lines that are unique
20 -i ignore case when comparing lines
21 -z lines end with \0 not \n
22 -w compare maximum X chars per line
23 -f ignore first X fields
24 -s ignore first X chars
37 static char *skip(char *str)
39 long nchars = TT.nchars, nfields;
42 for (nfields = TT.nfields; nfields; str++) {
43 while (*str && isspace(*str)) str++;
44 while (*str && !isspace(*str)) str++;
48 while (*str && nchars--) str++;
53 static void print_line(FILE *f, char *line)
55 if (toys.optflags & (TT.repeats ? FLAG_u : FLAG_d)) return;
56 if (toys.optflags & FLAG_c) fprintf(f, "%7lu ", TT.repeats + 1);
58 if (toys.optflags & FLAG_z) fputc(0, f);
63 FILE *infile = stdin, *outfile = stdout;
64 char *thisline = NULL, *prevline = NULL, *tmpline, eol = '\n';
65 size_t thissize, prevsize = 0, tmpsize;
67 if (toys.optc >= 1) infile = xfopen(toys.optargs[0], "r");
68 if (toys.optc >= 2) outfile = xfopen(toys.optargs[1], "w");
70 if (toys.optflags & FLAG_z) eol = 0;
72 // If first line can't be read
73 if (getdelim(&prevline, &prevsize, eol, infile) < 0)
76 while (getdelim(&thisline, &thissize, eol, infile) > 0) {
80 // If requested get the chosen fields + character offsets.
81 if (TT.nfields || TT.nchars) {
89 if (TT.maxchars == 0) {
90 diff = !(toys.optflags & FLAG_i) ? strcmp(t1, t2) : strcasecmp(t1, t2);
92 diff = !(toys.optflags & FLAG_i) ? strncmp(t1, t2, TT.maxchars)
93 : strncasecmp(t1, t2, TT.maxchars);
96 if (diff == 0) { // same
99 print_line(outfile, prevline);
113 print_line(outfile, prevline);
115 if (CFG_TOYBOX_FREE) {
116 if (outfile != stdout) fclose(outfile);
117 if (infile != stdin) fclose(infile);