<ก่อนหน้านี้ | Contents | ถัดไป>
การทดแทนกระบวนการ
แม้ว่าจะดูคล้ายกันและสามารถใช้เพื่อรวมสตรีมสำหรับการเปลี่ยนเส้นทางได้ แต่ก็มีความแตกต่างที่สำคัญระหว่างคำสั่งกลุ่มและเชลล์ย่อย ในขณะที่คำสั่งกลุ่มดำเนินการคำสั่งทั้งหมดในเชลล์ปัจจุบัน เชลล์ย่อย (ตามที่ชื่อแนะนำ) รันคำสั่งในสำเนาย่อยของเชลล์ปัจจุบัน ซึ่งหมายความว่าสภาพแวดล้อมจะถูกคัดลอกและมอบให้กับอินสแตนซ์ใหม่ของเชลล์ เมื่อ subshell ออก สำเนาของสภาพแวดล้อมจะสูญหาย ดังนั้นการเปลี่ยนแปลงใดๆ ที่เกิดขึ้นกับสภาพแวดล้อมของ subshell (รวมถึงการมอบหมายตัวแปร) จะสูญหายไปด้วย ดังนั้น ในกรณีส่วนใหญ่ เว้นแต่สคริปต์ต้องการเชลล์ย่อย คำสั่งกลุ่มจึงดีกว่าเชลล์ย่อย คำสั่งกลุ่มนั้นเร็วกว่าและต้องการหน่วยความจำน้อยกว่า
เราเห็นตัวอย่างของปัญหาสภาพแวดล้อม subshell ในบทที่ 28 เมื่อเราค้นพบว่า a อ่าน คำสั่งในไปป์ไลน์ไม่ทำงานอย่างที่เราคาดไว้โดยสัญชาตญาณ สรุป หากเราสร้างไพพ์ไลน์แบบนี้:
echo "foo" | อ่าน echo $REPLY
echo "foo" | อ่าน echo $REPLY
เนื้อหาของ ตอบ ตัวแปรจะว่างเสมอเพราะว่า อ่าน คำสั่งดำเนินการในเชลล์ย่อยและสำเนาของ ตอบ จะถูกทำลายเมื่อ subshell สิ้นสุดลง
เนื่องจากคำสั่งในไพพ์ไลน์จะถูกดำเนินการในเชลล์ย่อยเสมอ คำสั่งใดๆ ที่กำหนดให้ตัวแปรจะประสบปัญหานี้ โชคดีที่เปลือกมีการขยายตัวที่เรียกว่า กระบวนการทดแทน ที่สามารถใช้แก้ปัญหานี้ได้
การทดแทนกระบวนการแสดงได้สองวิธี: สำหรับกระบวนการที่สร้างเอาต์พุตมาตรฐาน:
<(รายการ)
หรือสำหรับกระบวนการที่รับอินพุตมาตรฐาน:
>(รายการ)
ที่ไหน รายการ เป็นรายการคำสั่ง
เพื่อแก้ปัญหาของเราด้วย อ่านเราสามารถใช้การทดแทนกระบวนการได้ดังนี้:
อ่าน <<(echo "foo") echo $REPLY
อ่าน <<(echo "foo") echo $REPLY
การทดแทนกระบวนการช่วยให้เราสามารถปฏิบัติต่อเอาต์พุตของ subshell เป็นไฟล์ธรรมดาสำหรับจุดประสงค์ของการเปลี่ยนเส้นทาง ในความเป็นจริง เนื่องจากเป็นรูปแบบการขยาย เราสามารถตรวจสอบมูลค่าที่แท้จริงของมันได้:
[me@linuxbox ~]$ echo <(echo "foo")
/dev/fd/63
[me@linuxbox ~]$ echo <(echo "foo")
/dev/fd/63
โดยใช้ เสียงสะท้อน เพื่อดูผลลัพธ์ของการขยาย เราจะเห็นว่าผลลัพธ์ของ subshell นั้นมาจากไฟล์ชื่อ /dev/fd/63.
การทดแทนกระบวนการมักใช้กับลูปที่มี อ่าน. นี่คือตัวอย่างของ
read loop ที่ประมวลผลเนื้อหาของรายการไดเร็กทอรีที่สร้างโดย subshell:
#! / bin / ทุบตี
# pro-sub: การสาธิตการทดแทนกระบวนการ
ในขณะที่อ่านลิงค์เจ้าของกลุ่มขนาดวันที่เวลาชื่อไฟล์; ทำแมว <<- EOF
ชื่อไฟล์: $ชื่อไฟล์ ขนาด: $size
เจ้าของ: $owner
กลุ่ม: $group แก้ไข: $date $time ลิงก์: $links คุณสมบัติ: $attr
EOF
เสร็จแล้ว <<(ls -l | หาง -n +2)
#! / bin / ทุบตี
# pro-sub: การสาธิตการทดแทนกระบวนการ
ในขณะที่อ่านลิงค์เจ้าของกลุ่มขนาดวันที่เวลาชื่อไฟล์; ทำแมว <<- EOF
ชื่อไฟล์: $ชื่อไฟล์ ขนาด: $size
เจ้าของ: $owner
กลุ่ม: $group แก้ไข: $date $time ลิงก์: $links คุณสมบัติ: $attr
EOF
เสร็จแล้ว <<(ls -l | หาง -n +2)
วนรอบดำเนินการ อ่าน สำหรับแต่ละบรรทัดของรายการไดเร็กทอรี รายชื่อผลิตในบรรทัดสุดท้ายของสคริปต์ บรรทัดนี้เปลี่ยนเส้นทางเอาต์พุตของการทดแทนกระบวนการไปยังอินพุตมาตรฐานของลูป NS หาง คำสั่งรวมอยู่ในไปป์ไลน์การทดแทนกระบวนการเพื่อกำจัดบรรทัดแรกของรายการซึ่งไม่จำเป็น
เมื่อดำเนินการ สคริปต์จะสร้างผลลัพธ์ดังนี้:
[me@linuxbox ~]$ โปรย่อย | หัว -n 20
ชื่อไฟล์: address.ldif ขนาด: 14540
เจ้าของ: me
กลุ่ม: ฉัน
Modified: 2009-04-02 11:12
[me@linuxbox ~]$ โปรย่อย | หัว -n 20
ชื่อไฟล์: address.ldif ขนาด: 14540
เจ้าของ: me
กลุ่ม: ฉัน
Modified: 2009-04-02 11:12
ลิงค์:
1
ลิงค์:
คุณสมบัติ: -rw-r--r--
ชื่อไฟล์: bin
ขนาด: 4096
เจ้าของ: me
กลุ่ม: ฉัน
Modified: 2009-07-10 07:31
ลิงค์: 2
แอตทริบิวต์: drwxr-xr-x
ชื่อไฟล์: bookmarks.html ขนาด: 394213
เจ้าของ: me
กลุ่ม: ฉัน
คุณสมบัติ: -rw-r--r--
ชื่อไฟล์: bin
ขนาด: 4096
เจ้าของ: me
กลุ่ม: ฉัน
Modified: 2009-07-10 07:31
ลิงค์: 2
แอตทริบิวต์: drwxr-xr-x
ชื่อไฟล์: bookmarks.html ขนาด: 394213
เจ้าของ: me
กลุ่ม: ฉัน