Con básicamente cualquier caparazón:
printf '{ PS4=\${$(($#-$x))}; } 2>&3; 2>&1\n%.0s' |
x=LINENO+1 sh -sx "$@" 3>/dev/null
Y no necesitas usar subshell. Por ejemplo:
set -x a b c
{ last= PS4=\${last:=\${$#}}; set +x; } 2>/dev/null
echo "$last"
...huellas dactilares...
c
Y aquí hay una función de shell que puede establecer un shell alias
para usted que imprimirá los argumentos hacia adelante o hacia atrás:
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
No intenta almacenar los valores literales para ningún argumento, sino que coloca una cadena como esta en args
alias
:
:;printf "%.$(($??${#*}:0))s%.$((!$??${#*}:0))s\n" \
"$1" "${3}" "${2}" "${2}" "${3}" "${1}"
... y almacena solo referencias a los parámetros hacia atrás y hacia adelante. Almacenará hasta un recuento dado como argumento. Y así, lo anterior alias
se generó como:
tofro 3
printf
El comportamiento de 's se ve afectado en función del valor de retorno del comando anterior, que siempre es :
el comando nulo y, por lo tanto, generalmente es verdadero. printf
omitirá la mitad de sus argumentos cada vez que imprima, lo que, de forma predeterminada, imprimirá los argumentos de menor a mayor número. Sin embargo, si solo haces:
! args
... los imprime al revés.
Debido a que el alias no almacena ningún valor literal, su valor permanece estático mientras que los argumentos reales pueden cambiar, pero aún hará referencia a tantos como podría. Por ejemplo:
set one two three
tofro 3
args; ! args
shift; args; ! args
... que imprime ...
one
two
three
three
two
one
two
three
three
two
Pero restablecer el alias se puede hacer así:
tofro 2
args; ! args
... y así se imprime ...
two
three
three
two
arg
ya que están ordenados correctamente y no a la inversa. Para el uso deexpr
, estoy limitado a usar solo el estándar.