mirror of
https://codeberg.org/landley/toybox.git
synced 2026-01-26 14:13:25 +00:00
Add sort -h (human readable), have -u imply -s, and general cleanup.
This commit is contained in:
parent
9e0547cb94
commit
e28e5bb465
@ -88,7 +88,7 @@ testing "key edge case with -t" "sort -n -k4 -t/" \
|
||||
/usr/lib/prebaseconfig.d/6
|
||||
"
|
||||
|
||||
testing "-x" "sort -x" "010\na0\n 0c0\n" "" "a0\n010\n 0c0\n"
|
||||
toyonly testing "-x" "sort -x" "010\na0\n 0c0\n" "" "a0\n010\n 0c0\n"
|
||||
|
||||
# Test that -f applies to key or fallback independently
|
||||
|
||||
@ -97,10 +97,12 @@ testing "" "sort -k2,2" "a B C\na B a\nA b b\n" "" "a B a\nA b b\na B C\n"
|
||||
testing "" "sort -f -k2,2" "A b b\na B C\na B a\n" "" "a B a\nA b b\na B C\n"
|
||||
testing "" "sort -t, -k3n" "3,4,1,2\n4,1,2,3\n1,2,3,4\n2,3,4,1\n" "" \
|
||||
"1,2,3,4\n2,3,4,1\n4,1,2,3\n3,4,1,2\n"
|
||||
testing "-kx" "sort -k1,1x" "3\na\n0c\n" "" "0c\na\n3\n"
|
||||
toyonly testing "-kx" "sort -k1,1x" "3\na\n0c\n" "" "0c\na\n3\n"
|
||||
|
||||
testing "" "sort -V" "toy-2.37.tar.gz\ntoy-3.4.tar.gz\ntoy-3.12.tar.gz\ntoy-4.16-rc2.tar.gz\ntoy-4.16.tar.gz\n" "" \
|
||||
"toy-3.12.tar.gz\ntoy-2.37.tar.gz\ntoy-3.4.tar.gz\ntoy-4.16-rc2.tar.gz\ntoy-4.16.tar.gz"
|
||||
# This has irredeemable version skew on the host and no standard defining it.
|
||||
# testing "-V" "LANG=c sort -V" \
|
||||
# "toy-2.37.tar.gz\ntoy-3.4.tar.gz\ntoy-3.12.tar.gz\ntoy-4.16-rc2.tar.gz\ntoy-4.16.tar.gz\n" "" \
|
||||
# "toy-3.12.tar.gz\ntoy-2.37.tar.gz\ntoy-3.4.tar.gz\ntoy-4.16-rc2.tar.gz\ntoy-4.16.tar.gz"
|
||||
|
||||
optional SORT_FLOAT
|
||||
|
||||
@ -108,3 +110,12 @@ optional SORT_FLOAT
|
||||
testing "-g" "sort -g" \
|
||||
"bork\nNaN\n-inf\n0.4\n1.222\n01.37\n2.1\n+infinity\n" "" \
|
||||
"01.37\n1.222\n2.1\n0.4\nNaN\nbork\n-inf\n+infinity\n"
|
||||
|
||||
# -n without number sorts as leading zero, but fallback is whole string
|
||||
testcmd '-n without number sorts as leading zero' '-n' \
|
||||
'-1\n0A\n0D\nC\n1z\n3b\n' '' '1z\n0D\n3b\nC\n-1\n0A\n'
|
||||
|
||||
testcmd '-u implies -s' '-uk2,2n' 'zero 1\nthree 2\nfour 3\n' '' \
|
||||
'zero 1\none 1\nfour 3\ntwo 1\nthree 2\nalso 1'
|
||||
testcmd '-h' '-h' '1bx\n1by\n1x\n1x\n1y\n1Ky\n1Ky\n1ky\n1My\n1Gx\n1Gx\n' '' \
|
||||
'1bx\n1y\n1by\n1x\n1ky\n1x\n1Ky\n1Gx\n1Ky\n1Gx\n1My'
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
* Deviations from POSIX: Lots.
|
||||
* We invented -x
|
||||
|
||||
USE_SORT(NEWTOY(sort, USE_SORT_FLOAT("g")"S:T:m" "o:k*t:" "xVbMcszdfirun", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
|
||||
USE_SORT(NEWTOY(sort, USE_SORT_FLOAT("gh")"S:T:m" "o:k*t:" "xVbMcszdfirun", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
|
||||
|
||||
config SORT
|
||||
bool "sort"
|
||||
@ -24,6 +24,7 @@ config SORT
|
||||
-c Check whether input is sorted
|
||||
-d Dictionary order (use alphanumeric and whitespace chars only)
|
||||
-f Force uppercase (case insensitive sort)
|
||||
-h Human readable numbers
|
||||
-i Ignore nonprinting characters
|
||||
-M Month sort (jan, feb, etc)
|
||||
-x Hexadecimal numerical sort
|
||||
@ -61,7 +62,7 @@ GLOBALS(
|
||||
char *o, *T, S;
|
||||
|
||||
void *key_list;
|
||||
int linecount;
|
||||
unsigned linecount;
|
||||
char **lines, *name;
|
||||
)
|
||||
|
||||
@ -72,8 +73,7 @@ GLOBALS(
|
||||
|
||||
#define FLAG_bb (1<<31) // Ignore trailing blanks
|
||||
|
||||
struct sort_key
|
||||
{
|
||||
struct sort_key {
|
||||
struct sort_key *next_key; // linked list
|
||||
unsigned range[4]; // start word, start char, end word, end char
|
||||
int flags;
|
||||
@ -115,7 +115,7 @@ static char *get_key_data(char *str, struct sort_key *key, int flags)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!j) start=end;
|
||||
if (!j) start = end;
|
||||
}
|
||||
|
||||
// Key with explicit separator starts after the separator
|
||||
@ -194,7 +194,7 @@ static int compare_values(int flags, char *x, char *y)
|
||||
}
|
||||
if (yinf) return dy<0 ? 1 : -1;
|
||||
|
||||
return dx>dy ? 1 : (dx<dy ? -1 : 0);
|
||||
return dx<dy ? -1 : dx>dy;
|
||||
} else if (flags & FLAG_M) {
|
||||
struct tm thyme;
|
||||
int dx;
|
||||
@ -227,12 +227,24 @@ static int compare_values(int flags, char *x, char *y)
|
||||
}
|
||||
}
|
||||
return *x ? !!*y : -1;
|
||||
} else if (flags & FLAG_n) {
|
||||
} else if (flags & (FLAG_n|FLAG_h)) {
|
||||
// Full floating point version of -n
|
||||
if (CFG_SORT_FLOAT) {
|
||||
double dx = atof(x), dy = atof(y);
|
||||
char *xx = x, *units = "kmgtpez";
|
||||
double dxy[2];
|
||||
int i = 0;
|
||||
|
||||
return dx>dy ? 1 : (dx<dy ? -1 : 0);
|
||||
do {
|
||||
dxy[i] = estrtol(xx, &xx, 0);
|
||||
if (flags & FLAG_h) {
|
||||
if (isspace(*xx)) xx++;
|
||||
if (*xx && (xx = strchr(units, tolower(*xx))))
|
||||
do dxy[i] *= 1024; while (xx-->units);
|
||||
}
|
||||
xx = y;
|
||||
} while (!i++);
|
||||
|
||||
return dxy[0]<dxy[1] ? -1 : dxy[0]>dxy[1];
|
||||
// Integer version of -n for tiny systems
|
||||
} else return atoi(x)-atoi(y);
|
||||
|
||||
@ -247,8 +259,8 @@ static int compare_keys(const void *xarg, const void *yarg)
|
||||
char *x, *y, *xx = *(char **)xarg, *yy = *(char **)yarg;
|
||||
struct sort_key *key;
|
||||
|
||||
for (key=(struct sort_key *)TT.key_list; !retval && key; key = key->next_key){
|
||||
flags = key->flags ? key->flags : toys.optflags;
|
||||
for (key=(void *)TT.key_list; !retval && key; key = key->next_key) {
|
||||
flags = key->flags ? : toys.optflags;
|
||||
|
||||
// Chop out and modify key chunks, handling -dfib
|
||||
|
||||
@ -287,10 +299,8 @@ static void sort_lines(char **pline, long len)
|
||||
|
||||
// handle -c here so we don't allocate more memory than necessary.
|
||||
if (FLAG(c)) {
|
||||
int j = FLAG(u) ? -1 : 0;
|
||||
|
||||
if (TT.lines && compare_keys((void *)&TT.lines, &line)>j)
|
||||
error_exit("%s: Check line %d\n", TT.name, TT.linecount);
|
||||
if (TT.lines && compare_keys((void *)&TT.lines, &line)>-!!FLAG(u))
|
||||
error_exit("%s: Check line %u\n", TT.name, TT.linecount);
|
||||
free(TT.lines);
|
||||
TT.lines = (void *)line;
|
||||
} else {
|
||||
@ -310,7 +320,9 @@ static void sort_read(int fd, char *name)
|
||||
|
||||
void sort_main(void)
|
||||
{
|
||||
int idx, fd = 1;
|
||||
int idx, jdx, fd = 1;
|
||||
|
||||
if (FLAG(u)) toys.optflags |= FLAG_s;
|
||||
|
||||
// Parse -k sort keys.
|
||||
if (TT.k) {
|
||||
@ -318,39 +330,32 @@ void sort_main(void)
|
||||
|
||||
for (arg = TT.k; arg; arg = arg->next) {
|
||||
struct sort_key *key = add_key();
|
||||
char *temp;
|
||||
char *temp, *temp2, *optlist;
|
||||
int flag;
|
||||
|
||||
idx = 0;
|
||||
temp = arg->arg;
|
||||
while (*temp) {
|
||||
// Start of range
|
||||
key->range[2*idx] = (unsigned)strtol(temp, &temp, 10);
|
||||
if (*temp=='.')
|
||||
key->range[(2*idx)+1] = (unsigned)strtol(temp+1, &temp, 10);
|
||||
key->range[2*idx] = strtol(temp, &temp, 10);
|
||||
if (*temp=='.') key->range[(2*idx)+1] = strtol(temp+1, &temp, 10);
|
||||
|
||||
// Handle flags appended to a key type.
|
||||
for (;*temp;temp++) {
|
||||
char *temp2, *optlist;
|
||||
|
||||
// Note that a second comma becomes an "Unknown key" error.
|
||||
|
||||
// Second comma becomes an "Unknown key" error.
|
||||
if (*temp==',' && !idx++) {
|
||||
temp++;
|
||||
break;
|
||||
}
|
||||
|
||||
// Which flag is this?
|
||||
|
||||
optlist = toys.which->options;
|
||||
temp2 = strchr(optlist, *temp);
|
||||
flag = (1<<(optlist-temp2+strlen(optlist)-1));
|
||||
flag = 1<<(optlist-temp2+strlen(optlist)-1);
|
||||
|
||||
// Was it a flag that can apply to a key?
|
||||
|
||||
if (!temp2 || flag>FLAG_x
|
||||
|| (flag&(FLAG_u|FLAG_c|FLAG_s|FLAG_z)))
|
||||
{
|
||||
if (!temp2 || flag>FLAG_x || (flag&(FLAG_u|FLAG_c|FLAG_s|FLAG_z))) {
|
||||
toys.exitval = 2;
|
||||
error_exit("Unknown key option.");
|
||||
}
|
||||
@ -380,11 +385,8 @@ void sort_main(void)
|
||||
|
||||
// handle unique (-u)
|
||||
if (FLAG(u)) {
|
||||
int jdx;
|
||||
|
||||
for (jdx=0, idx=1; idx<TT.linecount; idx++) {
|
||||
if (!compare_keys(&TT.lines[jdx], &TT.lines[idx]))
|
||||
free(TT.lines[idx]);
|
||||
if (!compare_keys(&TT.lines[jdx], &TT.lines[idx])) free(TT.lines[idx]);
|
||||
else TT.lines[++jdx] = TT.lines[idx];
|
||||
}
|
||||
if (TT.linecount) TT.linecount = jdx+1;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user