Bash ตั้งแต่เวอร์ชั่น 4.3, feb 2014 (?) ได้รับการสนับสนุนอย่างชัดเจนสำหรับตัวแปรอ้างอิงหรือการอ้างอิงชื่อ (namerefs) นอกเหนือจาก "eval" ด้วยประสิทธิภาพที่เป็นประโยชน์และผลกระทบทางอ้อมซึ่งอาจชัดเจนในสคริปต์ของคุณและยากขึ้น เพื่อ "ลืมที่จะ 'eval' และต้องแก้ไขข้อผิดพลาดนี้":
declare [-aAfFgilnrtux] [-p] [name[=value] ...]
typeset [-aAfFgilnrtux] [-p] [name[=value] ...]
Declare variables and/or give them attributes
...
-n Give each name the nameref attribute, making it a name reference
to another variable. That other variable is defined by the value
of name. All references and assignments to name, except for⋅
changing the -n attribute itself, are performed on the variable
referenced by name's value. The -n attribute cannot be applied to
array variables.
...
When used in a function, declare and typeset make each name local,
as with the local command, unless the -g option is supplied...
และนอกจากนี้ยังมี:
พารามิเตอร์
ตัวแปรสามารถกำหนดแอตทริบิวต์ nameref ได้โดยใช้ตัวเลือก -n ไปยังคำสั่ง declare หรือ local builtin (ดูคำอธิบายของการประกาศและ local ด้านล่าง) เพื่อสร้าง nameref หรืออ้างอิงกับตัวแปรอื่น สิ่งนี้ยอมให้ตัวแปรถูกควบคุมทางอ้อม เมื่อใดก็ตามที่มีการอ้างอิงหรือกำหนดตัวแปร nameref การดำเนินการจะดำเนินการกับตัวแปรที่ระบุโดยค่าของตัวแปร nameref โดยทั่วไปแล้ว nameref จะใช้ในฟังก์ชั่นเชลล์เพื่ออ้างถึงตัวแปรที่มีชื่อถูกส่งผ่านเป็นอาร์กิวเมนต์เพื่อฟังก์ชั่น ตัวอย่างเช่นหากชื่อตัวแปรถูกส่งผ่านไปยังฟังก์ชันเชลล์เป็นอาร์กิวเมนต์แรกให้เรียกใช้
declare -n ref=$1
ภายในฟังก์ชั่นสร้างการอ้างอิงตัวแปร nameref ที่มีค่าเป็นชื่อตัวแปรที่ส่งผ่านเป็นอาร์กิวเมนต์แรก การอ้างอิงและการมอบหมายให้อ้างอิงจะถือว่าเป็นการอ้างอิงและการมอบหมายให้กับตัวแปรที่มีชื่อผ่านเป็น⋅ $ 1 หากตัวแปรควบคุมใน for for มีแอตทริบิวต์ nameref รายการคำสามารถเป็นรายการของตัวแปร shell และการอ้างอิงชื่อจะถูกสร้างขึ้นสำหรับแต่ละคำในรายการในทางกลับกันเมื่อมีการดำเนินการวนรอบ ไม่สามารถกำหนดตัวแปรอาร์เรย์ได้ อย่างไรก็ตามตัวแปร nameref สามารถอ้างอิงตัวแปรอาร์เรย์และตัวแปรอาร์เรย์ที่ห้อยลงมาได้ Namerefs สามารถตั้งค่าได้โดยใช้ตัวเลือก -n เพื่อ unset builtin มิฉะนั้นหากดำเนินการยกเลิกการตั้งค่าด้วยชื่อของตัวแปร nameref เป็นอาร์กิวเมนต์
ตัวอย่างเช่น ( แก้ไข 2 : (ขอขอบคุณคุณรอน) กำหนดชื่อ (นำหน้า) ชื่อตัวแปรฟังก์ชันภายในเพื่อลดการชนตัวแปรภายนอกซึ่งในที่สุดควรตอบได้อย่างถูกต้องปัญหาที่เกิดขึ้นในคอมเม้นท์โดย Karsten):
# $1 : string; your variable to contain the return value
function return_a_string () {
declare -n ret=$1
local MYLIB_return_a_string_message="The date is "
MYLIB_return_a_string_message+=$(date)
ret=$MYLIB_return_a_string_message
}
และทดสอบตัวอย่างนี้:
$ return_a_string result; echo $result
The date is 20160817
โปรดทราบว่าการทุบตี "ประกาศ" builtin เมื่อใช้ในฟังก์ชั่นทำให้ตัวแปรประกาศ "ท้องถิ่น" โดยค่าเริ่มต้นและ "-n" ยังสามารถใช้กับ "ท้องถิ่น"
ฉันต้องการแยกความแตกต่าง "ประกาศสำคัญ" จากตัวแปร "น่าเบื่อท้องถิ่น" ดังนั้นการใช้ "ประกาศ" และ "ท้องถิ่น" ด้วยวิธีนี้ทำหน้าที่เป็นเอกสารประกอบ
แก้ไข 1 - (ตอบสนองต่อความคิดเห็นด้านล่างโดย Karsten) - ฉันไม่สามารถเพิ่มความคิดเห็นด้านล่างอีกต่อไป แต่ความคิดเห็นของ Karsten ทำให้ฉันคิดดังนั้นฉันจึงทำการทดสอบต่อไปนี้ซึ่ง WORKS FINE, AFAICT - Karsten ถ้าคุณอ่านสิ่งนี้ ของขั้นตอนการทดสอบจากบรรทัดคำสั่งแสดงปัญหาที่คุณคิดว่ามีอยู่เพราะขั้นตอนต่อไปนี้ใช้งานได้ดี:
$ return_a_string ret; echo $ret
The date is 20170104
(ตอนนี้ฉันวิ่งแค่นี้หลังจากวางฟังก์ชันด้านบนเป็นคำทุบตี - อย่างที่คุณเห็นผลลัพธ์ก็ใช้ได้ดี)
function funcName {
คือไวยากรณ์ดั้งเดิมของ POSIX ล่วงหน้าที่สืบทอดมาจาก ksh ก่อนหน้า (ซึ่งมีความแตกต่างทางความหมายที่ bash ไม่ให้เกียรติ)funcName() {
โดยไม่function
ควรนำมาใช้แทน; ดูwiki.bash-hackers.org/scripting/obsolete