sort: add support for delimiter strings

Instead of just single characters.  This also fixes
some bugs in columns().  Example bug:

	$ printf "a b\nc b x\n" | sort -k 2,2 -k 1,1
This commit is contained in:
Jakob Kramer 2015-02-01 21:00:37 +01:00 committed by sin
parent ada69106b7
commit 2d9d224a1b
1 changed files with 28 additions and 25 deletions

53
sort.c
View File

@ -33,10 +33,11 @@ static struct kdlist *tail = NULL;
static void addkeydef(char *, int); static void addkeydef(char *, int);
static void check(FILE *); static void check(FILE *);
static int linecmp(const char **, const char **); static int linecmp(const char **, const char **);
static char *skipblank(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 *nextcol(char *); static char *skipblank(char *);
static char *skipnonblank(char *);
static char *skipcolumn(char *, char *, int);
static char *columns(char *, const struct keydef *); static char *columns(char *, const struct keydef *);
static int Cflag = 0, cflag = 0, uflag = 0; static int Cflag = 0, cflag = 0, uflag = 0;
@ -173,24 +174,30 @@ parse_keydef(struct keydef *kd, char *s, int flags)
static char * static char *
skipblank(char *s) skipblank(char *s)
{ {
while (*s && isblank(*s)) while (isblank(*s))
s++; s++;
return s; return s;
} }
static char * static char *
nextcol(char *s) skipnonblank(char *s)
{ {
if (!fieldsep) { while (*s && *s != '\n' && !isblank(*s))
s = skipblank(s); s++;
while (*s && !isblank(*s)) return s;
s++; }
} else {
if (!strchr(s, *fieldsep)) static char *
s = strchr(s, '\0'); skipcolumn(char *s, char *eol, int next_col)
{
if (fieldsep) {
if ((s = strstr(s, fieldsep)))
s += next_col ? strlen(fieldsep) : 0;
else else
s = strchr(s, *fieldsep) + 1; s = eol;
} else {
s = skipblank(s);
s = skipnonblank(s);
} }
return s; return s;
} }
@ -198,30 +205,28 @@ nextcol(char *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, *eol = strchr(line, '\n');
int i; int i;
for (i = 1, start = line; i < kd->start_column; i++) for (i = 1, start = line; i < kd->start_column; i++)
start = nextcol(start); start = skipcolumn(start, eol, 1);
if (kd->flags & MOD_STARTB) if (kd->flags & MOD_STARTB)
start = skipblank(start); start = skipblank(start);
start += MIN(kd->start_char, nextcol(start) - start) - 1; start = MIN(eol, start + kd->start_char - 1);
if (kd->end_column) { if (kd->end_column) {
for (i = 1, end = line; i < kd->end_column; i++) for (i = 1, end = line; i < kd->end_column; i++)
end = nextcol(end); end = skipcolumn(end, eol, 1);
if (kd->flags & MOD_ENDB) if (kd->flags & MOD_ENDB)
end = skipblank(end); end = skipblank(end);
if (kd->end_char) if (kd->end_char)
end += MIN(kd->end_char, nextcol(end) - end); end = MIN(eol, end + kd->end_char);
else else
end = nextcol(end); end = skipcolumn(end, eol, 0);
} else { } else {
if (!(end = strchr(line, '\n'))) end = eol;
end = strchr(line, '\0');
} }
return enstrndup(2, start, start > end ? 0 : end - start);
return enstrndup(2, start, end - start);
} }
static void static void
@ -270,8 +275,6 @@ main(int argc, char *argv[])
break; break;
case 't': case 't':
fieldsep = EARGF(usage()); fieldsep = EARGF(usage());
if (strlen(fieldsep) != 1)
usage();
break; break;
case 'u': case 'u':
uflag = 1; uflag = 1;