ปัญหามาเยือนแล้ว
ค่อนข้างตรงไปตรงมาคู่มือมีความสับสนในประเด็นนี้ คู่มือ GNU ทุบตีพูดว่า:
สภาพแวดล้อมสำหรับคำสั่งหรือฟังก์ชันง่ายๆ [โปรดทราบว่าสิ่งนี้ไม่รวมบิวด์อิน] อาจถูกเติมเต็มชั่วคราวโดยการกำหนดค่าพารามิเตอร์ตามที่อธิบายไว้ในพารามิเตอร์ของเชลล์ คำสั่งมอบหมายเหล่านี้มีผลต่อสภาพแวดล้อมที่เห็นโดยคำสั่งนั้นเท่านั้น
หากคุณแยกวิเคราะห์ประโยคจริงๆสิ่งที่พูดคือสภาพแวดล้อมสำหรับคำสั่ง / ฟังก์ชันถูกแก้ไข แต่ไม่ใช่สภาพแวดล้อมสำหรับกระบวนการหลัก ดังนั้นสิ่งนี้จะได้ผล:
$ TESTVAR=bbb env | fgrep TESTVAR
TESTVAR=bbb
เนื่องจากสภาพแวดล้อมสำหรับคำสั่ง env ถูกแก้ไขก่อนที่จะดำเนินการ อย่างไรก็ตามสิ่งนี้จะไม่ทำงาน:
$ set -x; TESTVAR=bbb echo aaa $TESTVAR ccc
+ TESTVAR=bbb
+ echo aaa ccc
aaa ccc
เนื่องจากเมื่อทำการขยายพารามิเตอร์โดยเชลล์
ขั้นตอนล่าม
อีกส่วนหนึ่งของปัญหาคือ Bash กำหนดขั้นตอนเหล่านี้สำหรับล่าม:
- อ่านอินพุตจากไฟล์ (ดู Shell Scripts) จากสตริงที่ให้มาเป็นอาร์กิวเมนต์ไปยังอ็อพชันการเรียกใช้ -c (ดูที่การเรียกใช้ Bash) หรือจากเทอร์มินัลของผู้ใช้
- แบ่งการป้อนข้อมูลเป็นคำและตัวดำเนินการโดยปฏิบัติตามกฎการอ้างอิงที่อธิบายไว้ในการอ้างอิง โทเค็นเหล่านี้ถูกคั่นด้วยอักขระเมตา ขั้นตอนนี้ดำเนินการขยายนามแฝง (ดูนามแฝง)
- แยกวิเคราะห์โทเค็นเป็นคำสั่งแบบง่ายและแบบผสม (ดูคำสั่งเชลล์)
- ดำเนินการขยายเชลล์ต่างๆ (ดูที่การขยายเชลล์) โดยแยกโทเค็นที่ขยายออกเป็นรายการชื่อไฟล์ (ดูการขยายชื่อไฟล์) และคำสั่งและอาร์กิวเมนต์
- ดำเนินการเปลี่ยนเส้นทางที่จำเป็น (ดูการเปลี่ยนเส้นทาง) และลบตัวดำเนินการเปลี่ยนเส้นทางและตัวถูกดำเนินการออกจากรายการอาร์กิวเมนต์
- ดำเนินการคำสั่ง (ดูที่การดำเนินการคำสั่ง)
- เลือกที่จะรอให้คำสั่งดำเนินการเสร็จสิ้นและรวบรวมสถานะการออก (ดูสถานะการออก)
สิ่งที่เกิดขึ้นที่นี่คือบิวด์อินไม่ได้รับสภาพแวดล้อมการดำเนินการของตนเองดังนั้นจึงไม่เห็นสภาพแวดล้อมที่แก้ไข นอกจากนี้คำสั่งง่ายๆ (เช่น / bin / echo) จะได้รับสภาพแวดล้อมที่ถูกปรับเปลี่ยน (ซึ่งเป็นสาเหตุที่ทำให้ตัวอย่าง env ใช้งานได้) แต่การขยายเชลล์เกิดขึ้นในสภาพแวดล้อมปัจจุบันในขั้นตอนที่ 4
กล่าวอีกนัยหนึ่งคุณไม่ได้ส่ง 'aaa $ TESTVAR ccc' ไปยัง / bin / echo; คุณกำลังส่งสตริง interpolated (ตามที่ขยายในสภาพแวดล้อมปัจจุบัน) ไปยัง / bin / echo ในกรณีนี้เนื่องจากสภาพแวดล้อมปัจจุบันไม่มีTESTVARคุณเพียงแค่ส่ง 'aaa ccc' ไปยังคำสั่ง
สรุป
เอกสารอาจชัดเจนกว่านี้มาก สิ่งที่ดีมี Stack Overflow!
ดูสิ่งนี้ด้วย
http://www.gnu.org/software/bash/manual/bashref.html#Command-Execution-Environment