วิธีที่ดีในการทำงานกับ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ยืมแนวคิดจากtypesetbuiltin ของ Korn เชลล์) ถ้าตัวแปรถูกตั้งค่าไว้แล้วdeclareจะไม่ประกาศตัวแปรใหม่และวิธีการมอบหมายนั้นขึ้นอยู่กับประเภทของตัวแปร
ตัวอย่างเช่น
varname=foo
varvalue='([PATH=1000]=something)'
declare "$varname=$varvalue"
จะผลิตได้ผลที่แตกต่างกัน (และอาจมีผลข้างเคียงที่น่ารังเกียจ) ถ้าvarnameมีการประกาศก่อนหน้านี้ว่าเป็นสเกลาร์ , อาเรย์หรืออาเรย์
evalวิธีการที่ผิด คุณกำลังขยายตัว$var_valueก่อนที่จะส่งผ่านevalซึ่งหมายความว่ามันจะถูกตีความว่าเป็นรหัสเชลล์! (ลองกับvar_value="';:(){ :|:&};:'")