ฉันเข้าใจไวยากรณ์ของ subshell (<commands...>)
เป็น$()
เพียง subshell ที่คุณสามารถดึงค่าตัวแปรได้หรือไม่
หมายเหตุ: สิ่งนี้ใช้กับทุบตี 4.4 ตามถ้อยคำต่าง ๆ ในเอกสารประกอบ
ฉันเข้าใจไวยากรณ์ของ subshell (<commands...>)
เป็น$()
เพียง subshell ที่คุณสามารถดึงค่าตัวแปรได้หรือไม่
หมายเหตุ: สิ่งนี้ใช้กับทุบตี 4.4 ตามถ้อยคำต่าง ๆ ในเอกสารประกอบ
คำตอบ:
$(…)
เป็น subshell ตามคำนิยาม: เป็นสำเนาของ shell runtime state shell, และการเปลี่ยนแปลงสถานะที่ทำใน subshell ไม่มีผลกระทบกับ parent โดยทั่วไปแล้ว subshell จะถูกนำไปใช้โดยการฟอร์กกระบวนการใหม่ (แต่เชลล์บางตัวอาจปรับให้เหมาะสมในบางกรณี)
ไม่ใช่ subshell ที่คุณสามารถดึงค่าตัวแปรได้ หากการเปลี่ยนแปลงตัวแปรมีผลกระทบกับพาเรนต์มันจะไม่ใช่ subshell มันเป็น subshell ที่เอาท์พุทพาเรนต์สามารถดึงได้ เชลล์ย่อยที่สร้างโดย$(…)
มีเอาต์พุตมาตรฐานถูกตั้งค่าเป็นไพพ์และพาเรนต์อ่านจากไพพ์นั้นและรวบรวมเอาต์พุต
มีโครงสร้างอื่น ๆ อีกมากมายที่สร้างเชลล์ย่อย ฉันคิดว่านี่เป็นรายการที่สมบูรณ์สำหรับทุบตี:
( … )
ไม่ทำอะไรเลยนอกจากสร้าง subshell และรอให้มันยุติ) ความคมชัด{ … }
ที่กลุ่มคำสั่งอย่างหมดจดเพื่อวัตถุประสงค์ในการสร้างประโยคและไม่สร้างเชลล์ย่อย… &
สร้าง subshell และไม่รอให้มันจบ… | …
สร้างสอง subshells หนึ่งสำหรับด้านซ้ายมือและอีกหนึ่งสำหรับด้านขวามือและรอให้ทั้งสองจะยุติ เชลล์สร้างไพพ์และเชื่อมต่อเอาต์พุตมาตรฐานของด้านซ้ายมือกับปลายเขียนของไพพ์และอินพุตมาตรฐานของด้านขวาไปยังปลายอ่าน ในเชลล์บางตัว (ksh88, ksh93, zsh, bash พร้อมชุดlastpipe
ตัวเลือกและมีผลบังคับใช้) ทางด้านขวามือจะทำงานในเชลล์เดิมดังนั้นการสร้างไปป์ไลน์จะสร้างเชลล์ย่อยเดียวเท่านั้น$(…)
(สะกดเช่นกัน`…`
) สร้างเชลล์ย่อยพร้อมชุดเอาต์พุตมาตรฐานไปยังไพพ์รวบรวมเอาต์พุตในพาเรนต์และขยายไปยังเอาต์พุตนั้นลบบรรทัดใหม่ที่ต่อท้าย (และผลลัพธ์อาจขึ้นอยู่กับการแยกและการโค้งงอ แต่เป็นอีกเรื่อง)<(…)
สร้างเชลล์ย่อยพร้อมชุดเอาต์พุตมาตรฐานไปยังไพพ์และขยายเป็นชื่อของไพพ์ ผู้ปกครอง (หรือกระบวนการอื่น ๆ ) อาจเปิดไปป์เพื่อสื่อสารกับ subshell >(…)
ทำสิ่งเดียวกัน แต่กับไพพ์บนอินพุตมาตรฐานcoproc …
สร้าง subshell และไม่รอให้มันยุติ อินพุตและเอาต์พุตมาตรฐานของ subshell แต่ละชุดถูกตั้งค่าเป็นไพพ์โดยที่พาเรนต์เชื่อมต่อกับปลายอีกด้านของแต่ละไพพ์${...}
ไว้ในคำตอบได้หรือไม่?
command | { read line; … }
(ขึ้นอยู่กับเปลือกline
อาจหรือไม่อาจยังคงมีอยู่หลังจากท่อ) วิธีทั้งหมดเกี่ยวข้องกับเชลล์ย่อยเนื่องจากคำสั่งที่สร้างเอาต์พุตต้องรันโดยอิสระจากเชลล์ที่อ่านอินพุต หากคำสั่งนั้นอยู่ภายในเชลล์อย่างหมดจด (เฉพาะเชลล์สร้างและบิวด์อินไม่มีคำสั่งภายนอก) เชลล์อาจไม่สร้างกระบวนการย่อย แต่นั่นเป็นเพียงการเพิ่มประสิทธิภาพ แต่ยังคงสร้างเชลล์ย่อย
จากหน้า man (1) bash ใน bash เวอร์ชัน 4.4, ส่วน "EXPANSION", ส่วนย่อย "การแทนที่คำสั่ง":
Bash ทำการขยายตัวโดยดำเนินการ
command
ในสภาพแวดล้อม subshell [... ]
bash
manpage ไม่ได้พูดถึง subshell ใด ๆ : Bash performs the expansion by executing command and replacing the command substitution with the standard output of the command, with any trailing newlines deleted.
ฉันสงสัยว่านี่เป็นการละเลยโดยเจตนา
ใช่( commands... )
เป็นbash
subshell ที่จะดำเนินการcommands...
ในกระบวนการอื่น
ความแตกต่างเฉพาะเมื่อคุณมี$( commands... )
ก็คือส่วนหนึ่งของรหัสนี้จะหลังจากการดำเนินการของcommands...
ถูกแทนที่ด้วยทุกอย่างที่เขียนถึงcommands...
stdout