อัปเดต: บางคนบอกว่าไม่ควรใช้ eval ฉันไม่เห็นด้วย. evalผมคิดว่ามีความเสี่ยงที่เกิดขึ้นเมื่อป้อนข้อมูลเสียหายสามารถส่งผ่านไป อย่างไรก็ตามมีหลายสถานการณ์ทั่วไปที่ไม่เสี่ยงและดังนั้นจึงควรรู้วิธีใช้ eval ในกรณีใด ๆ คำตอบ stackoverflowนี้อธิบายถึงความเสี่ยงของการประเมินและทางเลือกในการประเมิน ในที่สุดมันก็ขึ้นอยู่กับผู้ใช้เพื่อตรวจสอบว่า / เมื่อ eval ปลอดภัยและมีประสิทธิภาพในการใช้
evalคำสั่งbash อนุญาตให้คุณรันบรรทัดของโค้ดที่คำนวณหรือได้มาโดยสคริปต์ bash ของคุณ
บางทีตัวอย่างที่ตรงไปตรงมาที่สุดอาจเป็นโปรแกรมทุบตีที่เปิดสคริปต์ทุบตีอื่นเป็นไฟล์ข้อความอ่านแต่ละบรรทัดของข้อความและใช้evalในการดำเนินการตามลำดับ นั่นเป็นพฤติกรรมแบบเดียวกับsourceคำสั่งbash ซึ่งเป็นสิ่งที่เราจะใช้นอกเสียจากว่าจำเป็นต้องทำการแปลงรูปแบบบางอย่าง (เช่นการกรองหรือการแทนที่) กับเนื้อหาของสคริปต์ที่นำเข้า
ฉันไม่ค่อยต้องการevalแต่ฉันพบว่ามีประโยชน์ในการอ่านหรือเขียนตัวแปรที่มีชื่ออยู่ในสตริงที่กำหนดให้กับตัวแปรอื่น ๆ ตัวอย่างเช่นในการดำเนินการกับชุดของตัวแปรในขณะที่รักษา footprint รหัสให้เล็กและหลีกเลี่ยงความซ้ำซ้อน
evalเป็นแนวคิดที่เรียบง่าย อย่างไรก็ตามไวยากรณ์ที่เข้มงวดของภาษาทุบตีและคำสั่งการแยกวิเคราะห์ของ bash interpreter สามารถเหมาะสมและทำให้evalปรากฏเป็นความลับและยากที่จะใช้หรือเข้าใจ นี่คือสิ่งจำเป็น:
- อาร์กิวเมนต์ที่ส่งผ่านไปยัง- evalเป็นนิพจน์สตริงที่คำนวณเมื่อรันไทม์- evalจะดำเนินการแยกวิเคราะห์ผลลัพธ์สุดท้ายของอาร์กิวเมนต์เป็นบรรทัดโค้ดจริงในสคริปต์ของคุณ
 
- ไวยากรณ์และคำสั่งแยกวิเคราะห์มีความเข้มงวด หากผลลัพธ์ไม่ใช่บรรทัดที่ใช้งานได้ของโค้ดทุบตีในขอบเขตของสคริปต์ของคุณโปรแกรมจะทำงานล้มเหลวใน- evalคำสั่งเนื่องจากพยายามเรียกใช้ขยะ
 
- เมื่อทดสอบคุณสามารถแทนที่- evalคำสั่งด้วย- echoและดูสิ่งที่จะปรากฏ หากเป็นรหัสที่ถูกต้องในบริบทปัจจุบันการเรียกใช้ผ่าน- evalจะทำงานได้
 
ตัวอย่างต่อไปนี้อาจช่วยให้ชัดเจนว่า eval ทำงานอย่างไร ...
ตัวอย่างที่ 1: 
eval คำสั่งหน้ารหัส 'ปกติ' คือ NOP
$ eval a=b
$ eval echo $a
b
ในตัวอย่างข้างต้นevalคำสั่งแรกไม่มีวัตถุประสงค์และสามารถตัดออกได้ evalไม่มีจุดหมายในบรรทัดแรกเนื่องจากไม่มีการกำหนดโค้ดแบบไดนามิกนั่นคือมันแยกวิเคราะห์แล้วในบรรทัดสุดท้ายของรหัสทุบตีดังนั้นมันจะเหมือนกับคำสั่งปกติของรหัสในสคริปต์ทุบตี ลำดับที่ 2 evalนั้นไม่มีจุดหมายเช่นกันเพราะถึงแม้ว่าจะมีขั้นตอนการแยกวิเคราะห์เป็น$aสตริงตัวอักษรที่เทียบเท่ากัน แต่ก็ไม่มีทางอ้อม (เช่นไม่มีการอ้างอิงผ่านค่าสตริงของคำนาม bash จริงหรือตัวแปรสคริปต์ที่ถือ bash) ดังนั้นมันจะทำงานเหมือนกัน เป็นบรรทัดของรหัสโดยไม่มีevalคำนำหน้า
ตัวอย่างที่ 2: 
ดำเนินการกำหนด var โดยใช้ชื่อ var ที่ส่งผ่านเป็นค่าสตริง
$ key="mykey"
$ val="myval"
$ eval $key=$val
$ echo $mykey
myval
หากคุณต้องการecho $key=$valผลลัพธ์จะเป็น:
mykey=myval
นั่นคือผลลัพธ์สุดท้ายของการแยกสตริงคือสิ่งที่จะถูกประมวลผลโดย eval ดังนั้นผลลัพธ์ของคำสั่ง echo ในตอนท้าย ...
ตัวอย่างที่ 3:
การเพิ่มทางอ้อมให้กับตัวอย่างที่ 2
$ keyA="keyB"
$ valA="valB"
$ keyB="that"
$ valB="amazing"
$ eval eval \$$keyA=\$$valA
$ echo $that
amazing
ข้างต้นเป็นบิตที่ซับซ้อนกว่าตัวอย่างก่อนหน้านี้อาศัยอย่างหนักในการแยกคำสั่งและลักษณะของการทุบตี evalบรรทัดประมาณจะได้รับการแยกวิเคราะห์ภายในในลำดับต่อไปนี้(หมายเหตุงบต่อไปนี้ pseudocode ไม่รหัสจริงเพียงแค่พยายามที่จะแสดงให้เห็นว่าคำสั่งที่จะได้รับแบ่งออกเป็นขั้นตอนภายในที่จะมาถึงผลสุดท้าย)
 eval eval \$$keyA=\$$valA  # substitution of $keyA and $valA by interpreter
 eval eval \$keyB=\$valB    # convert '$' + name-strings to real vars by eval
 eval $keyB=$valB           # substitution of $keyB and $valB by interpreter
 eval that=amazing          # execute string literal 'that=amazing' by eval
หากคำสั่งการแยกวิเคราะห์ที่สันนิษฐานไม่ได้อธิบายว่า eval ทำอะไรได้พอตัวอย่างที่สามอาจอธิบายการแยกวิเคราะห์อย่างละเอียดเพื่อช่วยอธิบายสิ่งที่เกิดขึ้น
ตัวอย่างที่ 4: 
ค้นพบว่า vars ซึ่งมีชื่ออยู่ในสตริงมีค่าสตริงหรือไม่
a="User-provided"
b="Another user-provided optional value"
c=""
myvarname_a="a"
myvarname_b="b"
myvarname_c="c"
for varname in "myvarname_a" "myvarname_b" "myvarname_c"; do
    eval varval=\$$varname
    if [ -z "$varval" ]; then
        read -p "$varname? " $varname
    fi
done
ในการทำซ้ำครั้งแรก:
varname="myvarname_a"
Bash วิเคราะห์ข้อโต้แย้งevalและevalเห็นอย่างนี้เมื่อรันไทม์:
eval varval=\$$myvarname_a
ต่อไปนี้pseudocodeความพยายามที่จะแสดงให้เห็นถึงวิธีการตีความทุบตีบรรทัดข้างต้นของจริงevalรหัสที่จะมาถึงค่าสุดท้ายที่ดำเนินการโดย (บรรทัดอธิบายต่อไปนี้ไม่ใช่รหัสทุบตีที่แน่นอน):
1. eval varval="\$" + "$varname"      # This substitution resolved in eval statement
2. .................. "$myvarname_a"  # $myvarname_a previously resolved by for-loop
3. .................. "a"             # ... to this value
4. eval "varval=$a"                   # This requires one more parsing step
5. eval varval="User-provided"        # Final result of parsing (eval executes this)
เมื่อแยกวิเคราะห์เสร็จแล้วผลลัพธ์ก็คือสิ่งที่ถูกดำเนินการและผลกระทบที่เห็นได้ชัดแสดงให้เห็นว่าไม่มีอะไรลึกลับโดยเฉพาะเกี่ยวกับevalตัวเองและความซับซ้อนอยู่ในการแยกวิเคราะห์ของมัน
varval="User-provided"
รหัสที่เหลืออยู่ในตัวอย่างด้านบนจะทำการทดสอบเพื่อดูว่าค่าที่กำหนดให้กับ $ varval เป็นโมฆะหรือไม่และหากเป็นเช่นนั้นจะแจ้งให้ผู้ใช้ระบุค่า
               
              
$($n)ทำงาน$nใน subshell มันพยายามรันคำสั่ง1ที่ไม่มีอยู่