Is there a way to sort the list of positional parameters in POSIX sh? Each positional parameter could contain arbitrary characters (e.g. spaces, newlines, tabs, etc.). The sort algorithm should be general enough to sort the list based on any comparison defined by the programmer (e.g. numeric/lexicographical sorting using expr
comparison, sorting that considers only a substring of each positional parameter, etc.).
It seems that POSIX sh's list of positional arguments has the characteristics of both a stack and a queue. It supports push (set -- "$x" "$@"
), pop (x="$1"; shift
), enqueue (set -- "$@" "$x"
) and dequeue (x="$1"; shift
) operations. However, there can only be a single list, which means that sorting must be done in-place and I cannot use common algorithms such as merge sort and quicksort.
Sample:
#!/bin/sh
set -- "Hello" "world" 9 8 7 "$(printf "0\n1")" "$(printf "1\t2")"
How do I sort the positional parameters above using comparison
expr "$x" \< "$y"
such that the result is the list below?
"$(printf "0\n1")" "$(printf "1\t2")" 9 8 7 "Hello" "world"
Note 1: I am looking for a POSIX solution that works for arbitrary positional arguments supplied by a user and arbitrary comparisons specified by the programmer.
Note 2: I am not trying to solve any practical problem. I have challenged myself to this sh
sorting problem but I could not come up with a solution, so I am posting it here on Stack Exchange.
sort
and reading the file are not what you're after, right? – terdon Nov 19 '23 at 16:36set -- "${@:1: $#-1}"
, but it's not POSIX and will croak if the list if empty to begin with.) This is probably one of those things that would be better done in another programming language with better support for data structures. – ilkkachu Nov 19 '23 at 17:15x=$1 y=$2; shift; shift; set -- "$y" "$x" "$@"
, though, but generalizing that to an arbitrary pair, or even an arbitrary consecutive pair gets rather difficult. – ilkkachu Nov 19 '23 at 17:23e1
,e2
etc. and doeval
tricks to "index" that, but that way lies madness. You can't really even shove the values to an outside program (likesort
), since to be able to hold arbitrary values, you'd need to read NUL-separated output back from the program, and that's not really easy POSIXly. – ilkkachu Nov 19 '23 at 17:25