З основною будь-якою оболонкою:
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
на поведінку поведінки впливає виходячи із значення повернення попередньої команди - що завжди :
є нульовою командою, і так зазвичай істинно. 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
, я обмежуюсь лише використанням стандарту.