Con praticamente qualsiasi shell:
printf '{ PS4=\${$(($#-$x))}; } 2>&3; 2>&1\n%.0s' |
x=LINENO+1 sh -sx "$@" 3>/dev/null
E non è necessario utilizzare i subshells. Per esempio:
set -x a b c
{ last= PS4=\${last:=\${$#}}; set +x; } 2>/dev/null
echo "$last"
... stampe ...
c
Ed ecco una funzione di shell che può impostare una shell alias
per te che stamperà gli argomenti in avanti o indietro:
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
Non tenta di memorizzare i valori letterali per nessun argomento, ma inserisce una stringa come questa nel args
alias
:
:;printf "%.$(($??${#*}:0))s%.$((!$??${#*}:0))s\n" \
"$1" "${3}" "${2}" "${2}" "${3}" "${1}"
... e quindi memorizza solo i riferimenti ai parametri avanti e indietro. Memorizzerà fino a un conteggio come indicato come argomento. E così quanto sopra è alias
stato generato come:
tofro 3
printf
Il comportamento è influenzato in base al valore restituito dal comando precedente, che è sempre :
il comando null, e quindi di solito vero. printf
salterà la metà dei suoi argomenti ogni volta che stampa - che, per impostazione predefinita, otterrà gli argomenti stampati dal più piccolo numerato al più grande. Tuttavia, se lo fai solo:
! args
... li stampa al contrario.
Poiché l'alias non memorizza alcun valore letterale, il suo valore rimane statico mentre gli argomenti reali potrebbero cambiare, ma farà comunque riferimento a quanti ne potrebbe. Per esempio:
set one two three
tofro 3
args; ! args
shift; args; ! args
... che stampa ...
one
two
three
three
two
one
two
three
three
two
Ma il ripristino dell'alias può essere fatto come:
tofro 2
args; ! args
... e così stampa ...
two
three
three
two
arg
perché sono ordinati correttamente e non al contrario. Per l'uso diexpr
, sono limitato a utilizzare solo lo standard.