ด้วยพื้นเปลือกใด ๆ :
printf '{ PS4=\${$(($#-$x))}; } 2>&3; 2>&1\n%.0s' |
x=LINENO+1 sh -sx "$@" 3>/dev/null
และคุณไม่จำเป็นต้องใช้ subshells ตัวอย่างเช่น:
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
พฤติกรรมของได้รับผลกระทบโดยขึ้นอยู่กับค่าส่งคืนของคำสั่งก่อนหน้าซึ่งมักจะ:
เป็นคำสั่ง null และมักจะเป็นจริง printf
จะข้ามข้อโต้แย้งไปครึ่งหนึ่งในแต่ละครั้งที่พิมพ์ซึ่งตามค่าเริ่มต้นจะรับอาร์กิวเมนต์ที่พิมพ์จากหมายเลขที่เล็กที่สุดไปหามากที่สุด อย่างไรก็ตามถ้าคุณทำ:
! args
... มันพิมพ์กลับด้าน
เนื่องจากนามแฝงไม่ได้เก็บค่าตามตัวอักษรใด ๆ ค่าของมันจะยังคงอยู่ในขณะที่ 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
ฉันถูก จำกัด ให้ใช้มาตรฐานเท่านั้น