Dengan dasarnya semua shell:
printf '{ PS4=\${$(($#-$x))}; } 2>&3; 2>&1\n%.0s' |
x=LINENO+1 sh -sx "$@" 3>/dev/null
Dan Anda tidak perlu menggunakan subkulit. Sebagai contoh:
set -x a b c
{ last= PS4=\${last:=\${$#}}; set +x; } 2>/dev/null
echo "$last"
... mencetak ...
c
Dan di sini adalah fungsi shell yang dapat mengatur shell alias
untuk Anda yang akan mencetak argumen maju atau mundur:
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
Itu tidak berusaha untuk menyimpan nilai-nilai literal untuk argumen apa pun, melainkan menempatkan string seperti ini di args
alias
:
:;printf "%.$(($??${#*}:0))s%.$((!$??${#*}:0))s\n" \
"$1" "${3}" "${2}" "${2}" "${3}" "${1}"
... dan hanya menyimpan referensi ke parameter mundur dan maju. Ini akan menyimpan hingga hitungan sebagaimana diberikan sebagai argumen. Maka di atas alias
dihasilkan seperti:
tofro 3
printf
Perilaku dipengaruhi berdasarkan nilai kembali dari perintah sebelumnya - yang selalu :
merupakan perintah nol, dan biasanya benar. printf
akan melewatkan setengah dari argumennya setiap kali ia mencetak - yang, secara default, akan mendapatkan argumen yang dicetak dari yang paling kecil ke yang terbesar. Namun, jika Anda hanya melakukannya:
! args
... itu mencetaknya secara terbalik.
Karena alias tidak menyimpan nilai literal apa pun, nilainya tetap statis sementara arg yang sebenarnya mungkin berubah, tetapi masih akan merujuk sebanyak mungkin. Sebagai contoh:
set one two three
tofro 3
args; ! args
shift; args; ! args
... yang mencetak ...
one
two
three
three
two
one
two
three
three
two
Tetapi mengatur ulang alias bisa dilakukan seperti:
tofro 2
args; ! args
... dan itu mencetak ...
two
three
three
two
arg
karena mereka dipesan dengan benar dan tidak terbalik. Untuk penggunaanexpr
, saya terbatas hanya menggunakan standar.