$#
คือจำนวนอาร์กิวเมนต์ แต่โปรดจำไว้ว่ามันจะแตกต่างกันในฟังก์ชั่น
$#
คือจำนวนของพารามิเตอร์ตำแหน่งส่งผ่านไปยังสคริปต์เปลือกหรือฟังก์ชั่นเปลือก นี้เป็นเพราะในขณะที่ฟังก์ชั่นเชลล์กำลังทำงานพารามิเตอร์ตำแหน่งจะถูกแทนที่ชั่วคราวที่มีการขัดแย้งในการทำงาน ฟังก์ชันนี้อนุญาตให้ยอมรับและใช้พารามิเตอร์ตำแหน่งของตนเองได้
สคริปต์นี้พิมพ์ทุก3
ครั้งโดยไม่คำนึงถึงจำนวนอาร์กิวเมนต์ที่ส่งผ่านไปยังสคริปต์เองเนื่องจาก"$#"
ในฟังก์ชันf
จะขยายเป็นจำนวนอาร์กิวเมนต์ที่ส่งไปยังฟังก์ชัน:
#!/bin/sh
f() {
echo "$#"
}
f a b c
สิ่งนี้สำคัญเนื่องจากหมายความว่าโค้ดลักษณะนี้ไม่ทำงานอย่างที่คุณคาดไว้หากคุณไม่คุ้นเคยกับการทำงานของพารามิเตอร์ตำแหน่งในฟังก์ชันเชลล์:
#!/bin/sh
check_args() { # doesn't work!
if [ "$#" -ne 2 ]; then
printf '%s: error: need 2 arguments, got %d\n' "$0" "$#" >&2
exit 1
fi
}
# Maybe check some other things...
check_args
# Do other stuff...
ในcheck_args
, $#
ขยายจำนวนของอาร์กิวเมนต์ส่งผ่านไปยังฟังก์ชั่นของตัวเองซึ่งในสคริปต์ที่อยู่เสมอ 0
หากคุณต้องการฟังก์ชั่นดังกล่าวในฟังก์ชั่นเชลล์คุณจะต้องเขียนสิ่งนี้แทน:
#!/bin/sh
check_args() { # works -- the caller must pass the number of arguments received
if [ "$1" -ne 2 ]; then
printf '%s: error: need 2 arguments, got %d\n' "$0" "$1" >&2
exit 1
fi
}
# Maybe check some other things...
check_args "$#"
งานนี้เพราะ$#
มีการขยายออกไปข้างนอกฟังก์ชั่นและส่งผ่านไปยังฟังก์ชั่นเป็นหนึ่งในของพารามิเตอร์ตำแหน่ง ภายในฟังก์ชัน$1
ขยายไปยังพารามิเตอร์ตำแหน่งแรกที่ส่งผ่านไปยังฟังก์ชันเชลล์แทนที่จะไปยังสคริปต์ที่เป็นส่วนหนึ่งของ
ดังนั้นเช่น$#
พารามิเตอร์พิเศษ$1
, $2
ฯลฯ เช่นเดียวกับ$@
และ$*
ยังเกี่ยวข้องกับการขัดแย้งส่งผ่านไปยังฟังก์ชั่นเมื่อพวกเขาจะขยายตัวในการทำงาน อย่างไรก็ตาม$0
ไม่ได้เปลี่ยนเป็นชื่อของฟังก์ชั่นซึ่งเป็นสาเหตุที่ฉันยังสามารถใช้เพื่อสร้างข้อความแสดงข้อผิดพลาดที่มีคุณภาพ
$ ./check-args-demo a b c
./check-args-demo: error: need 2 arguments, got 3
ในทำนองเดียวกันถ้าคุณกำหนดหนึ่งฟังก์ชันภายในอีกฟังก์ชันหนึ่งคุณกำลังทำงานกับพารามิเตอร์ตำแหน่งที่ส่งผ่านไปยังฟังก์ชันด้านในสุดซึ่งมีการดำเนินการขยาย:
#!/bin/sh
outer() {
inner() {
printf 'inner() got %d arguments\n' "$#"
}
printf 'outer() got %d arguments\n' "$#"
inner x y z
}
printf 'script got %d arguments\n' "$#"
outer p q
ฉันเรียกสคริปต์นี้nested
และ (หลังจากทำงานchmod +x nested
) ฉันเรียกใช้มัน:
$ ./nested a
script got 1 arguments
outer() got 2 arguments
inner() got 3 arguments
ใช่ฉันรู้. "1 ข้อโต้แย้ง" เป็นข้อบกพร่องหลายฝ่าย
พารามิเตอร์ตำแหน่งยังสามารถเปลี่ยนแปลงได้
หากคุณกำลังเขียนสคริปต์พารามิเตอร์ตำแหน่งนอกฟังก์ชั่นจะเป็นอาร์กิวเมนต์บรรทัดคำสั่งที่ส่งไปยังสคริปต์เว้นแต่คุณจะมีการเปลี่ยนแปลงพวกเขา
วิธีทั่วไปในการเปลี่ยนแปลงคือshift
บิวอินซึ่งจะเปลี่ยนพารามิเตอร์ตำแหน่งไปทางซ้ายทีละหนึ่งแล้วปล่อยพารามิเตอร์แรกและลดลง$#
1:
#!/bin/sh
while [ "$#" -ne 0 ]; do
printf '%d argument(s) remaining.\nGot "%s".\n\n' "$#" "$1"
shift
done
$ ./do-shift foo bar baz # I named the script do-shift.
3 argument(s) remaining.
Got "foo".
2 argument(s) remaining.
Got "bar".
1 argument(s) remaining.
Got "baz".
พวกเขาสามารถเปลี่ยนแปลงได้ด้วยset
builtin:
#!/bin/sh
printf '%d args: %s\n' "$#" "$*"
set foo bar baz
printf '%d args: %s\n' "$#" "$*"
$ ./set-args a b c d e # I named the script set-args.
5 args: a b c d e
3 args: foo bar baz
$#
? คุณต้องการทำอะไรให้สำเร็จ คุณได้รับคำสั่งนี้จากที่ไหน มันไม่เกี่ยวข้องเลย