ความแตกต่างที่สำคัญที่สุดระหว่าง
bash -c "$1"
และ
eval "$1"
คือว่าอดีตทำงานใน subshell และหลังไม่ได้ ดังนั้น:
set -- 'var=something'
bash -c "$1"
echo "$var"
เอาท์พุท:
#there doesn't seem to be anything here
set -- 'var=something'
eval "$1"
echo "$var"
เอาท์พุท:
something
ฉันไม่มีความคิดว่าทำไมทุกคนจะใช้ความสามารถbash
ในการปฏิบัติการในลักษณะนั้น หากคุณต้องเรียกใช้ให้ใช้ POSIX รับประกันในsh
ตัว หรือ(subshell eval)
ถ้าคุณต้องการปกป้องสภาพแวดล้อมของคุณ
โดยส่วนตัวแล้วฉันชอบเชลล์.dot
มากกว่าสิ่งอื่นใด
printf 'var=something%d ; echo "$var"\n' `seq 1 5` | . /dev/fd/0
เอาท์พุท
something1
something2
something3
something4
something5
แต่คุณต้องการมันทั้งหมดหรือไม่
สาเหตุเดียวที่จะใช้อย่างใดอย่างหนึ่งจริง ๆ คือในกรณีที่ตัวแปรของคุณกำหนดหรือประเมินอื่นจริง ๆ หรือการแบ่งคำเป็นสิ่งสำคัญสำหรับผลลัพธ์
ตัวอย่างเช่น
var='echo this is var' ; $var
เอาท์พุท:
this is var
ใช้งานได้ แต่เพียงเพราะecho
ไม่สนใจเกี่ยวกับการนับอาร์กิวเมนต์
var='echo "this is var"' ; $var
เอาท์พุท:
"this is var"
ดู? สองคำพูดมาพร้อมเพราะผลของการขยายตัวของเปลือกของไม่ได้ประเมิน$var
quote-removal
var='printf %s\\n "this is var"' ; $var
เอาท์พุท:
"this
is
var"
แต่ด้วยeval
หรือsh
:
var='echo "this is var"' ; eval "$var" ; sh -c "$var"
เอาท์พุท:
this is var
this is var
เมื่อเราใช้eval
หรือsh
เชลล์ใช้การส่งผ่านครั้งที่สองที่ผลลัพธ์ของการขยายและประเมินว่ามันเป็นคำสั่งที่มีศักยภาพเช่นกันดังนั้นราคาจะสร้างความแตกต่าง คุณยังสามารถทำสิ่งต่อไปนี้
. <<VAR /dev/fd/0
${var:=echo "this is var"}
#END
VAR
เอาท์พุท
this is var
e='echo foo'; $e
ทำงานได้ดี