С практически любой оболочкой:
printf '{ PS4=\${$(($#-$x))}; } 2>&3; 2>&1\n%.0s' |
x=LINENO+1 sh -sx "$@" 3>/dev/null
И вам не нужно использовать подоболочки. Например:
set -x a b c
{ last= PS4=\${last:=\${$#}}; set +x; } 2>/dev/null
echo "$last"
... печать ...
c
А вот функция оболочки, которая может установить alias
для вас оболочку , которая будет печатать аргументы вперед или назад:
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
Он не пытается сохранить литеральные значения для каких-либо аргументов, скорее он помещает строку, подобную этой, в args
alias
:
:;printf "%.$(($??${#*}:0))s%.$((!$??${#*}:0))s\n" \
"$1" "${3}" "${2}" "${2}" "${3}" "${1}"
... и сохраняет только ссылки на параметры в прямом и обратном направлении. Он будет хранить до количества, указанного в качестве аргумента. И так выше alias
было сгенерировано как:
tofro 3
printf
Поведение зависит от возвращаемого значения предыдущей команды, которая всегда :
является пустой командой, и поэтому обычно имеет значение true. printf
будет пропускать половину своих аргументов каждый раз, когда он печатает, что по умолчанию выводит аргументы с наименьшего номера на самый большой. Однако, если вы просто делаете:
! args
... он печатает их в обратном порядке.
Поскольку псевдоним не хранит никаких литеральных значений, его значение остается статическим, в то время как фактические аргументы могут измениться, но он все равно будет ссылаться на столько, сколько мог бы. Например:
set one two three
tofro 3
args; ! args
shift; args; ! args
... который печатает ...
one
two
three
three
two
one
two
three
three
two
Но сброс псевдонима можно сделать так:
tofro 2
args; ! args
... и так печатает ...
two
three
three
two
arg
поскольку они заказаны правильно, а не в обратном порядке. Для использованияexpr
я ограничен в использовании только стандарта.