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ć alias
dla 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 alias
zostało wygenerowane jak:
tofro 3
printf
Na zachowanie ma wpływ wartość zwracana z poprzedniego polecenia - które zawsze jest :
poleceniem zerowym, a więc zwykle prawdziwe. printf
pominie 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
arg
ponieważ są one uporządkowane poprawnie, a nie odwrotnie. Do użyciaexpr
ograniczam się tylko do korzystania ze standardu.