Z praktycznie każdą powłoką:
printf '{ PS4=\${$(($#-$x))}; } 2>&3; 2>&1\n%.0s' |
x=LINENO+1 sh -sx "$@" 3>/dev/null
I nie musisz używać podpowłoki. Na przykład:
set -x a b c
{ last= PS4=\${last:=\${$#}}; set +x; } 2>/dev/null
echo "$last"
... drukuje ...
c
A oto funkcja powłoki, która może ustawić aliasdla ciebie powłokę , która wypisze argumenty do przodu lub do tyłu:
tofro() case $1 in (*[!0-9]*|'') ! :;;(*) set "$1"
until [ "$1" -eq "$(($#-1))" ] &&
shift && alias args=":; printf \
\"%.\$((\$??\${#*}:0))s%.\$((!\$??\${#*}:0))s\n\" $* "
do [ "$#" -gt 1 ] &&
set "$@ \"\${$#}\" " '"${'"$((1+$1-$#))"'}"' ||
set "$1" '"$1" "${'"$1"'}"'
done; esac
Nie próbuje przechowywać wartości literałów dla żadnych argumentów, ale umieszcza taki ciąg w args alias:
:;printf "%.$(($??${#*}:0))s%.$((!$??${#*}:0))s\n" \
"$1" "${3}" "${2}" "${2}" "${3}" "${1}"
... i dlatego przechowuje tylko odniesienia do parametrów wstecz i do przodu. Będzie przechowywać do liczby podanej jako argument. Tak więc powyższe aliaszostało wygenerowane jak:
tofro 3
printfNa zachowanie ma wpływ wartość zwracana z poprzedniego polecenia - które zawsze jest :poleceniem zerowym, a więc zwykle prawdziwe. printfpominie połowę swoich argumentów przy każdym drukowaniu - co domyślnie spowoduje wydrukowanie argumentów od najmniejszej do największej. Jeśli jednak po prostu to zrobisz:
! args
... drukuje je w odwrotnej kolejności.
Ponieważ alias nie przechowuje żadnych literalnych wartości, jego wartość pozostaje statyczna, podczas gdy rzeczywiste argumenty mogą się zmieniać, ale nadal będzie odwoływać się do tylu, ile może. Na przykład:
set one two three
tofro 3
args; ! args
shift; args; ! args
... które drukuje ...
one
two
three
three
two
one
two
three
three
two
Ale resetowanie aliasu można wykonać w następujący sposób:
tofro 2
args; ! args
... i tak drukuje ...
two
three
three
two
argponieważ są one uporządkowane poprawnie, a nie odwrotnie. Do użyciaexprograniczam się tylko do korzystania ze standardu.