คุณสามารถใช้ here-doc และ จัดหามาสำหรับรุ่นตัวรวบรวมทั่วไปที่มีประสิทธิภาพและเป็นมิตร POSIX
. 8<<-\IOHERE /proc/self/fd/8
command
…
fn() { declaration ; } <<WHATEVER
# though a nested heredoc might be finicky
# about stdin depending on shell
WHATEVER
cat -u ./stdout | ./works.as >> expect.ed
IOHERE
เมื่อคุณเปิด heredoc คุณจะส่งสัญญาณเชลล์ด้วยโทเค็นอินพุต IOHERE ที่ควรเปลี่ยนทิศทางอินพุตไปยัง file-descriptor ที่คุณระบุจนกว่าจะพบที่ปลายอีกด้านของโทเค็นตัว จำกัด ของคุณ ฉันมองไปรอบ ๆ แต่ฉันไม่เห็นตัวอย่างของการใช้หมายเลข fd การเปลี่ยนเส้นทางตามที่ฉันได้แสดงไว้ด้านบนร่วมกับตัวดำเนินการ heredoc ถึงแม้ว่าการใช้จะถูกระบุไว้อย่างชัดเจนในแนวทางคำสั่งเชลล์คำสั่งพื้นฐาน POSIX คนส่วนใหญ่เพียงแค่ชี้ไปที่ stdin และ shoot แต่ฉันพบว่าการจัดหา scriptlets ด้วยวิธีนี้สามารถทำให้ stdin ฟรีและแอปที่เป็นส่วนประกอบจากการบ่นเกี่ยวกับเส้นทาง I / o ที่ถูกบล็อก
เนื้อหาของ heredoc จะถูกสตรีมไปยังไฟล์ descriptor ที่คุณระบุซึ่งจะถูกตีความว่าเป็นรหัสเชลล์และดำเนินการโดย builtin แต่ไม่ได้ระบุเส้นทางที่เฉพาะเจาะจงสำหรับ . หากพา ธ / proc / self ให้ปัญหากับคุณลอง / dev / fd / n หรือ / proc / $$ วิธีการเดียวกันนี้ทำงานบนท่อโดยวิธี:
cat ./*.sh | . /dev/stdin
อย่างน้อยก็อาจจะไม่ฉลาดเท่าที่ดู คุณสามารถทำเช่นเดียวกันกับ sh, แน่นอน แต่. วัตถุประสงค์คือเพื่อดำเนินการในสภาพแวดล้อมเชลล์ปัจจุบันซึ่งอาจเป็นสิ่งที่คุณต้องการและขึ้นอยู่กับเชลล์ของคุณมีแนวโน้มที่จะทำงานกับ heredoc มากกว่า ด้วยท่อที่ไม่ระบุชื่อมาตรฐาน
อย่างไรก็ตามอย่างที่คุณอาจสังเกตเห็นว่าฉันยังไม่ได้ตอบคำถามของคุณ แต่ถ้าคุณคิดเกี่ยวกับมันในลักษณะเดียวกับที่ heredoc สตรีมรหัสทั้งหมดของคุณเป็น. in ก็ให้คุณหนึ่งจุดง่าย ๆ ธรรมดา:
. 5<<EOIN /dev/fd/5 |\
tee -a ./log.file | cat -u >$(tty)
script
…
more script
EOIN
ดังนั้นเทอร์มินัล stdout ทั้งหมดจากรหัสใด ๆ ที่ดำเนินการใน heredoc ของคุณจะถูกส่งออกมา เป็นเรื่องของหลักสูตรและสามารถทีจะออกจากท่อเดียวได้อย่างง่ายดาย ฉันรวมการเรียกแมวที่ไม่มีบัฟเฟอร์เพราะฉันไม่ชัดเจนเกี่ยวกับทิศทาง stdout ปัจจุบัน แต่อาจซ้ำซ้อน
คุณอาจตั้งคำถามเครื่องหมายคำพูดทับขวาที่หายไปในตัวอย่างที่สอง ส่วนนี้เป็นสิ่งสำคัญที่จะต้องเข้าใจก่อนที่คุณจะข้ามไปและอาจให้แนวคิดเล็กน้อยเกี่ยวกับวิธีการใช้งาน ตัว จำกัด heredoc ที่ยกมา (จนถึงตอนนี้เราใช้ IOHERE และ EOIN แล้วและเป็นครั้งแรกที่ฉันอ้างถึงแบ็กสแลชแม้ว่าเครื่องหมายอัญประกาศ "เดี่ยว" หรือ "สองเท่า" จะให้บริการเพื่อจุดประสงค์เดียวกัน) จะป้องกันเชลล์จากการขยายพารามิเตอร์ใด ๆ เนื้อหา แต่ตัว จำกัด ที่ไม่ได้กล่าวถึงจะเปิดเนื้อหาไว้เพื่อขยาย ผลที่ตามมาจากสิ่งนี้เมื่อคุณได้รับสิ่งนี้ มีที่มาอย่างมาก:
. 3<<HD ${fdpath}/3
: \${vars=$(printf '${var%s=$((%s*2))},' `seq 1 100`)}
HD
echo $vars
> 4,8,12…
echo $var1 $var51
> 4 104
เนื่องจากฉันไม่ได้อ้างอิงตัว จำกัด heredoc เชลล์จึงขยายเนื้อหาตามที่อ่านในและก่อนที่จะแสดง descriptor ไฟล์ผลลัพธ์ เพื่อดำเนินการ สิ่งนี้ส่งผลให้คำสั่งถูกวิเคราะห์คำสองครั้ง - คำสั่งที่ขยายได้ เนื่องจาก I backslash อ้างถึงการขยายพารามิเตอร์ $ vars เชลล์จึงเพิกเฉยต่อการประกาศในรอบแรกและถอดเฉพาะแบ็กสแลชเพื่อให้เนื้อหาที่ถูกขยายการพิมพ์ printf ทั้งหมดสามารถถูกประเมินด้วย null เมื่อ สคริปต์ที่มาจากแหล่งที่สอง
ฟังก์ชั่นนี้โดยพื้นฐานแล้วสิ่งที่เปลือก eval ที่เป็นอันตรายสามารถจัดหาให้ได้แม้ว่าการอ้างจะง่ายต่อการจัดการใน heredoc มากกว่าการ eval และอาจเป็นอันตรายเท่า ๆ กัน หากคุณไม่ได้วางแผนอย่างรอบคอบคุณควรอ้างตัว จำกัด "EOF" ว่าเป็นเรื่องของนิสัย แค่พูด.
แก้ไข: เอ๊ะฉันกำลังมองกลับไปที่นี้และคิดว่ามันยืดเกินไปเล็กน้อย หากสิ่งที่คุณต้องทำคือเชื่อมเอาท์พุทหลาย ๆ ตัวให้เป็นไพพ์เดียวดังนั้นวิธีที่ง่ายที่สุดคือใช้:
{ or ( command ) list ; } | tee -a ea.sy >>pea.sy
curlies จะพยายามเรียกใช้เนื้อหาในเชลล์ปัจจุบันในขณะที่ parens จะย่อยออกโดยอัตโนมัติ ยังคงมีใครสามารถบอกคุณได้ว่าอย่างน้อยในความคิดของฉัน วิธีการแก้ปัญหา heredoc เป็นข้อมูลที่มีค่ามากกว่าโดยเฉพาะอย่างยิ่งถ้าคุณต้องการที่จะเข้าใจว่าเชลล์ทำงานอย่างไร
มีความสุข!