Add -d, -f and -i flags to sort(1)

Here's the patch with updated manpage and usage().
This commit is contained in:
pekka.jylha.ollila@gmail.com 2016-02-16 02:42:25 +02:00 committed by sin
parent ae52820891
commit fad1d35357
2 changed files with 69 additions and 2 deletions

8
sort.1
View File

@ -6,7 +6,7 @@
.Nd sort lines .Nd sort lines
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Op Fl Cbcmnru .Op Fl Cbcdfimnru
.Op Fl o Ar outfile .Op Fl o Ar outfile
.Op Fl t Ar delim .Op Fl t Ar delim
.Op Fl k Ar key ... .Op Fl k Ar key ...
@ -35,6 +35,12 @@ The same as
.Fl C .Fl C
except that when disorder is detected, a message is written to stderr except that when disorder is detected, a message is written to stderr
indicating the location of the disorder. indicating the location of the disorder.
.It Fl d
Skip non-whitespace and non-alphanumeric characters.
.It Fl f
Ignore letter case when sorting.
.It FL i
Skip non-printable characters.
.It Fl k Ar key .It Fl k Ar key
Specify a key definition of the form Specify a key definition of the form
.Sm off .Sm off

63
sort.c
View File

@ -23,6 +23,9 @@ enum {
MOD_STARTB = 1 << 1, MOD_STARTB = 1 << 1,
MOD_ENDB = 1 << 2, MOD_ENDB = 1 << 2,
MOD_R = 1 << 3, MOD_R = 1 << 3,
MOD_D = 1 << 4,
MOD_F = 1 << 5,
MOD_I = 1 << 6,
}; };
static TAILQ_HEAD(kdhead, keydef) kdhead = TAILQ_HEAD_INITIALIZER(kdhead); static TAILQ_HEAD(kdhead, keydef) kdhead = TAILQ_HEAD_INITIALIZER(kdhead);
@ -115,6 +118,44 @@ columns(char *line, const struct keydef *kd, char **col, size_t *colsiz)
return len; return len;
} }
static int
skipmodcmp(const char *s1, const char *s2, int flags)
{
Rune r1, r2;
do {
s1 += chartorune(&r1, s1);
s2 += chartorune(&r2, s2);
if (flags & MOD_D && flags & MOD_I) {
while (*s1 && ((!isblankrune(r1) && !isalnumrune(r1)) ||
(!isprintrune(r1))))
s1 += chartorune(&r1, s1);
while (*s2 && ((!isblankrune(r2) && !isalnumrune(r2)) ||
(!isprintrune(r2))))
s2 += chartorune(&r2, s2);
}
else if (flags & MOD_D) {
while (*s1 && !isblankrune(r1) && !isalnumrune(r1))
s1 += chartorune(&r1, s1);
while (*s2 && !isblankrune(r2) && !isalnumrune(r2))
s2 += chartorune(&r2, s2);
}
else if (flags & MOD_I) {
while (*s1 && !isprintrune(r1))
s1 += chartorune(&r1, s1);
while (*s2 && !isprintrune(r2))
s2 += chartorune(&r2, s2);
}
if (flags & MOD_F) {
r1 = toupperrune(r1);
r2 = toupperrune(r2);
}
} while (r1 && r1 == r2);
return r1 - r2;
}
static int static int
linecmp(const char **a, const char **b) linecmp(const char **a, const char **b)
{ {
@ -135,6 +176,8 @@ linecmp(const char **a, const char **b)
x = strtold(col1, NULL); x = strtold(col1, NULL);
y = strtold(col2, NULL); y = strtold(col2, NULL);
res = (x < y) ? -1 : (x > y); res = (x < y) ? -1 : (x > y);
} else if (kd->flags & (MOD_D | MOD_F | MOD_I)) {
res = skipmodcmp(col1, col2, kd->flags);
} else { } else {
res = strcmp(col1, col2); res = strcmp(col1, col2);
} }
@ -178,6 +221,15 @@ parse_flags(char **s, int *flags, int bflag)
case 'b': case 'b':
*flags |= bflag; *flags |= bflag;
break; break;
case 'd':
*flags |= MOD_D;
break;
case 'f':
*flags |= MOD_F;
break;
case 'i':
*flags |= MOD_I;
break;
case 'n': case 'n':
*flags |= MOD_N; *flags |= MOD_N;
break; break;
@ -240,7 +292,7 @@ addkeydef(char *kdstr, int flags)
static void static void
usage(void) usage(void)
{ {
enprintf(2, "usage: %s [-Cbcmnru] [-o outfile] [-t delim] " enprintf(2, "usage: %s [-Cbcdfimnru] [-o outfile] [-t delim] "
"[-k def]... [file ...]\n", argv0); "[-k def]... [file ...]\n", argv0);
} }
@ -263,6 +315,15 @@ main(int argc, char *argv[])
case 'c': case 'c':
cflag = 1; cflag = 1;
break; break;
case 'd':
global_flags |= MOD_D;
break;
case 'f':
global_flags |= MOD_F;
break;
case 'i':
global_flags |= MOD_I;
break;
case 'k': case 'k':
addkeydef(EARGF(usage()), global_flags); addkeydef(EARGF(usage()), global_flags);
break; break;