วิธีที่ดีในการทำงานกับeval
คือแทนที่ด้วยecho
สำหรับการทดสอบ echo
และeval
ทำงานเหมือนเดิม (ถ้าเราแยกการ\x
ขยายที่ดำเนินการโดยecho
การใช้งานบางอย่างเช่นbash
'ภายใต้เงื่อนไขบางอย่าง)
ทั้งสองคำสั่งเข้าร่วมการโต้เถียงกับหนึ่งช่องว่างในระหว่าง ความแตกต่างคือecho
แสดงผลในขณะที่eval
ประเมิน / ตีความเป็นรหัสเชลล์ผลลัพธ์
ดังนั้นเพื่อดูว่ารหัสเปลือก
eval $(echo $var_name=$var_value)
จะประเมินคุณสามารถเรียกใช้:
$ echo $(echo $var_name=$var_value)
fruit=blue orange
นั่นไม่ใช่สิ่งที่คุณต้องการสิ่งที่คุณต้องการคือ:
fruit=$var_value
นอกจากนี้การใช้$(echo ...)
ที่นี่ก็ไม่สมเหตุสมผล
ในการแสดงผลด้านบนคุณจะต้องเรียกใช้:
$ echo "$var_name=\$var_value"
fruit=$var_value
ดังนั้นในการตีความมันนั่นเป็นเพียง:
eval "$var_name=\$var_value"
โปรดทราบว่ามันยังสามารถใช้เพื่อตั้งค่าองค์ประกอบอาร์เรย์แต่ละรายการ:
var_name='myarray[23]'
var_value='something'
eval "$var_name=\$var_value"
อย่างที่คนอื่นพูดถ้าคุณไม่สนใจรหัสที่bash
เจาะจงคุณสามารถใช้declare
เป็น:
declare "$var_name=$var_value"
อย่างไรก็ตามโปรดทราบว่ามันมีผลข้างเคียงบางอย่าง
มัน จำกัด ขอบเขตของตัวแปรไว้ที่ฟังก์ชั่นที่มันทำงานอยู่ดังนั้นคุณไม่สามารถใช้มันเป็นตัวอย่างในสิ่งต่าง ๆ เช่น:
setvar() {
var_name=$1 var_value=$2
declare "$var_name=$var_value"
}
setvar foo bar
เพราะนั่นจะประกาศfoo
ตัวแปรท้องถิ่นเพื่อsetvar
ดังนั้นจะไร้ประโยชน์
bash-4.2
เพิ่ม-g
ตัวเลือกสำหรับdeclare
การประกาศตัวแปรทั่วโลกแต่นั่นไม่ใช่สิ่งที่เราต้องการอย่างใดอย่างหนึ่งตามที่เราsetvar
จะกำหนดvar ทั่วโลกเมื่อเทียบกับที่ของผู้โทรถ้าโทรเป็นฟังก์ชั่นเช่นใน:
setvar() {
var_name=$1 var_value=$2
declare -g "$var_name=$var_value"
}
foo() {
local myvar
setvar myvar 'some value'
echo "1: $myvar"
}
foo
echo "2: $myvar"
ซึ่งจะเอาท์พุท:
1:
2: some value
นอกจากนี้โปรดทราบว่าในขณะที่declare
เรียกว่าdeclare
(จริง ๆ แล้วbash
ยืมแนวคิดจากtypeset
builtin ของ Korn เชลล์) ถ้าตัวแปรถูกตั้งค่าไว้แล้วdeclare
จะไม่ประกาศตัวแปรใหม่และวิธีการมอบหมายนั้นขึ้นอยู่กับประเภทของตัวแปร
ตัวอย่างเช่น
varname=foo
varvalue='([PATH=1000]=something)'
declare "$varname=$varvalue"
จะผลิตได้ผลที่แตกต่างกัน (และอาจมีผลข้างเคียงที่น่ารังเกียจ) ถ้าvarname
มีการประกาศก่อนหน้านี้ว่าเป็นสเกลาร์ , อาเรย์หรืออาเรย์
eval
วิธีการที่ผิด คุณกำลังขยายตัว$var_value
ก่อนที่จะส่งผ่านeval
ซึ่งหมายความว่ามันจะถูกตีความว่าเป็นรหัสเชลล์! (ลองกับvar_value="';:(){ :|:&};:'"
)