add -t flag to sort

This commit is contained in:
Jakob Kramer 2014-05-15 20:08:17 +02:00 committed by sin
parent 2ab2d2ee3b
commit 7d1fd2621e
2 changed files with 54 additions and 54 deletions

28
sort.1
View File

@ -4,9 +4,10 @@ sort \- sort lines
.SH SYNOPSIS .SH SYNOPSIS
.B sort .B sort
.RB [ \-bnru ] .RB [ \-bnru ]
.RB [ \-t
.IR delim ]
.RB [ \-k .RB [ \-k
.I key .IR key ]...
.R ]...
.RI [ file ...] .RI [ file ...]
.SH DESCRIPTION .SH DESCRIPTION
.B sort .B sort
@ -17,16 +18,7 @@ given, sort reads from stdin.
.B \-b .B \-b
skip leading whitespace of columns when sorting. skip leading whitespace of columns when sorting.
.TP .TP
.B \-n .BI \-k \ key
perform a numeric sort.
.TP
.B \-r
reverses the sort.
.TP
.B \-u
prints equal lines only once.
.TP
.B \-k key
specifies a key definition of the form specifies a key definition of the form
.BR S [. s ][ f ][, E [. e ][ f ]] .BR S [. s ][ f ][, E [. e ][ f ]]
where where
@ -50,3 +42,15 @@ can be used to specify options
that only apply to this key definition. that only apply to this key definition.
.B b .B b
is special in that it only applies to the column that it was specified after. is special in that it only applies to the column that it was specified after.
.TP
.B \-n
perform a numeric sort.
.TP
.B \-r
reverses the sort.
.TP
.BI \-t \ delim
specifies the field delimiter.
.TP
.B \-u
prints equal lines only once.

80
sort.c
View File

@ -34,20 +34,19 @@ static struct kdlist *tail = NULL;
static void addkeydef(char *, int); static void addkeydef(char *, int);
static void freelist(void); static void freelist(void);
static int linecmp(const char **, const char **); static int linecmp(const char **, const char **);
static char *next_nonblank(char *); static char *skipblank(char *);
static char *next_blank(char *);
static int parse_flags(char **, int *, int); static int parse_flags(char **, int *, int);
static int parse_keydef(struct keydef *, char *, int); static int parse_keydef(struct keydef *, char *, int);
static char *skip_columns(char *, size_t, bool); static char *nextcol(char *);
static char *end_column(char *);
static char *columns(char *, const struct keydef *); static char *columns(char *, const struct keydef *);
static bool uflag = false; static bool uflag = false;
static char *fieldsep = NULL;
static void static void
usage(void) usage(void)
{ {
enprintf(2, "usage: %s [-bnru] [-k def]... [file...]\n", argv0); enprintf(2, "usage: %s [-bnru] [-t delim] [-k def]... [file...]\n", argv0);
} }
int int
@ -59,21 +58,26 @@ main(int argc, char *argv[])
int global_flags = 0; int global_flags = 0;
ARGBEGIN { ARGBEGIN {
case 'b':
global_flags |= MOD_STARTB | MOD_ENDB;
break;
case 'k':
addkeydef(EARGF(usage()), global_flags);
break;
case 'n': case 'n':
global_flags |= MOD_N; global_flags |= MOD_N;
break; break;
case 'r': case 'r':
global_flags |= MOD_R; global_flags |= MOD_R;
break; break;
case 't':
fieldsep = EARGF(usage());
if(strlen(fieldsep) != 1)
usage();
break;
case 'u': case 'u':
uflag = true; uflag = true;
break; break;
case 'b':
global_flags |= MOD_STARTB | MOD_ENDB;
break;
case 'k':
addkeydef(EARGF(usage()), global_flags);
break;
default: default:
usage(); usage();
} ARGEND; } ARGEND;
@ -224,7 +228,7 @@ parse_keydef(struct keydef *kd, char *s, int flags)
} }
static char * static char *
next_nonblank(char *s) skipblank(char *s)
{ {
while(*s && isblank(*s)) while(*s && isblank(*s))
s++; s++;
@ -232,51 +236,43 @@ next_nonblank(char *s)
} }
static char * static char *
next_blank(char *s) nextcol(char *s)
{ {
while(*s && !isblank(*s)) if(fieldsep == NULL) {
s++; s = skipblank(s);
return s; while(*s && !isblank(*s))
} s++;
} else {
static char * if(strchr(s, *fieldsep) == NULL)
skip_columns(char *s, size_t n, bool bflag) s = strchr(s, '\0');
{ else
size_t i; s = strchr(s, *fieldsep) + 1;
for(i = 0; i < n; i++) {
if(i > 0)
s = end_column(s);
if(bflag)
s = next_nonblank(s);
} }
return s; return s;
} }
static char *
end_column(char *s)
{
if(isblank(*s))
s = next_nonblank(s);
return next_blank(s);
}
static char * static char *
columns(char *line, const struct keydef *kd) columns(char *line, const struct keydef *kd)
{ {
char *start, *end; char *start, *end;
char *res; char *res;
int i;
start = skip_columns(line, kd->start_column, kd->flags & MOD_STARTB); for(i = 1, start = line; i < kd->start_column; i++)
start += MIN(kd->start_char, end_column(start) - start) - 1; start = nextcol(start);
if(kd->flags & MOD_STARTB)
start = skipblank(start);
start += MIN(kd->start_char, nextcol(start) - start) - 1;
if(kd->end_column) { if(kd->end_column) {
end = skip_columns(line, kd->end_column, kd->flags & MOD_ENDB); for(i = 1, end = line; i < kd->end_column; i++)
end = nextcol(end);
if(kd->flags & MOD_ENDB)
end = skipblank(end);
if(kd->end_char) if(kd->end_char)
end += MIN(kd->end_char, end_column(end) - end); end += MIN(kd->end_char, nextcol(end) - end);
else else
end = end_column(end); end = nextcol(end);
} else { } else {
if((end = strchr(line, '\n')) == NULL) if((end = strchr(line, '\n')) == NULL)
end = strchr(line, '\0'); end = strchr(line, '\0');