Com basicamente qualquer shell:
printf '{ PS4=\${$(($#-$x))}; } 2>&3; 2>&1\n%.0s' |
x=LINENO+1 sh -sx "$@" 3>/dev/null
E você não precisa usar sub-conchas. Por exemplo:
set -x a b c
{ last= PS4=\${last:=\${$#}}; set +x; } 2>/dev/null
echo "$last"
... imprime ...
c
E aqui está uma função de shell que pode definir um shell alias
para você que imprimirá os argumentos para frente ou para trá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
Ele não tenta armazenar os valores literais para nenhum argumento, mas coloca uma string como esta no args
alias
:
:;printf "%.$(($??${#*}:0))s%.$((!$??${#*}:0))s\n" \
"$1" "${3}" "${2}" "${2}" "${3}" "${1}"
... e, portanto, armazena apenas referências aos parâmetros para trás e para frente. Ele armazenará até uma contagem, como dado como argumento. E assim o acima alias
foi gerado como:
tofro 3
printf
O comportamento do é afetado com base no valor de retorno do comando anterior - que é sempre :
o comando nulo e, portanto, geralmente verdadeiro. printf
pulará metade de seus argumentos sempre que imprimir - o que, por padrão, fará com que os argumentos sejam impressos do menor para o maior. No entanto, se você apenas fizer:
! args
... imprime-os ao contrário.
Como o alias não armazena nenhum valor literal, seu valor permanece estático enquanto os argumentos reais podem mudar, mas ainda fará referência a quantos forem. Por exemplo:
set one two three
tofro 3
args; ! args
shift; args; ! args
... que imprime ...
one
two
three
three
two
one
two
three
three
two
Mas a redefinição do alias pode ser feita como:
tofro 2
args; ! args
... e assim imprime ...
two
three
three
two
arg
pois eles estão ordenados corretamente e não ao contrário. Para o uso deexpr
, estou limitado a usar apenas o padrão.