$(<file)
(ยังทำงานร่วมกับ`<file`
) เป็นผู้ประกอบการพิเศษของเปลือกกรคัดลอกโดยและzsh
bash
มันดูคล้ายกับการทดแทนคำสั่ง แต่มันไม่จริง
ใน POSIX เชลล์คำสั่งง่าย ๆ คือ:
< file var1=value1 > file2 cmd 2> file3 args 3> file4
ชิ้นส่วนทั้งหมดเป็นทางเลือกคุณสามารถมีการเปลี่ยนเส้นทางเท่านั้นคำสั่งเท่านั้นกำหนดเท่านั้นหรือชุดค่าผสม
หากมีการเปลี่ยนเส้นทาง แต่ไม่มีคำสั่งการเปลี่ยนเส้นทางจะดำเนินการ (ดังนั้น> file
จะเปิดและตัดทอนfile
) แต่ไม่มีอะไรเกิดขึ้น ดังนั้น
< file
เปิดfile
ให้อ่าน แต่ไม่มีอะไรเกิดขึ้นเนื่องจากไม่มีคำสั่ง ดังนั้นจึงfile
ถูกปิดและนั่นก็คือ ถ้า$(< file)
เป็นการแทนคำสั่งแบบง่ายมันก็จะขยายออกเป็นไม่มีอะไรเลย
ในสเปค POSIXใน$(script)
ถ้าscript
ประกอบด้วยเดียวของการเปลี่ยนเส้นทางที่ก่อให้เกิดผลลัพธ์ที่ไม่ได้ระบุ นั่นคือการอนุญาตให้พฤติกรรมพิเศษของ Korn เชลล์
ใน ksh (ทดสอบที่นี่ด้วยksh93u+
) หากสคริปต์ประกอบด้วยคำสั่งง่าย ๆ เพียงคำสั่งเดียว (แม้ว่าความคิดเห็นจะได้รับอนุญาตก่อนและหลัง) ที่ประกอบด้วยการเปลี่ยนเส้นทางเท่านั้น (ไม่มีคำสั่งไม่มีการมอบหมาย) และหากการเปลี่ยนเส้นทางครั้งแรกคือ stdin (fd 0) การป้อนข้อมูลเท่านั้น ( <
, <<
หรือ<<<
) การเปลี่ยนเส้นทางเพื่อ:
$(< file)
$(0< file)
$(<&3)
( $(0>&3)
เช่นเดียวกับที่ใช้ในผู้ให้บริการรายเดียวกัน)
$(< file > foo 2> $(whatever))
แต่ไม่:
$(> foo < file)
- ไม่
$(0<> file)
- ไม่
$(< file; sleep 1)
- ไม่
$(< file; < file2)
แล้วก็
- ทั้งหมดยกเว้นการเปลี่ยนเส้นทางครั้งแรกจะถูกละเว้น (จะถูกแยกวิเคราะห์)
- และจะขยายเนื้อหาของไฟล์ / heredoc / herestring (หรืออะไรก็ตามที่สามารถอ่านได้จาก file descriptor หากใช้สิ่งต่าง ๆ เช่น
<&3
) ลบอักขระขึ้นบรรทัดใหม่
ราวกับว่าใช้$(cat < file)
ยกเว้นว่า
- การอ่านทำโดยเชลล์ภายในไม่ใช่การอ่าน
cat
- ไม่มีส่วนเกี่ยวข้องกับกระบวนการหรือท่อ
- เป็นผลมาจากข้างต้นเนื่องจากรหัสภายในไม่ได้ทำงานใน subshell การแก้ไขใด ๆ ที่ยังคงอยู่หลังจากนั้น (เช่นใน
$(<${file=foo.txt})
หรือ$(<file$((++n)))
)
- อ่านข้อผิดพลาด (แม้ว่าจะไม่ใช่ข้อผิดพลาดในขณะที่เปิดไฟล์หรือทำซ้ำไฟล์ descriptors) จะถูกละเว้นอย่างเงียบ ๆ
ในzsh
ก็เหมือนกันยกเว้นว่าพฤติกรรมพิเศษจะถูกเรียกเฉพาะเมื่อมีเพียงหนึ่งการเปลี่ยนเส้นทางการป้อนข้อมูลไฟล์ ( <file
หรือ0< file
ไม่<&3
, <<<here
, < a < b
... )
อย่างไรก็ตามยกเว้นเมื่อทำการจำลองเชลล์อื่น ๆ ใน:
< file
<&3
<<< here...
นั่นคือเมื่อมีการเปลี่ยนเส้นทางอินพุตเท่านั้นโดยไม่มีคำสั่งนอกการทดแทนคำสั่งzsh
รัน$READNULLCMD
(เพจเจอร์ตามค่าเริ่มต้น) และเมื่อมีทั้งการเปลี่ยนเส้นทางอินพุตและเอาต์พุตนั้น$NULLCMD
( cat
โดยค่าเริ่มต้น) ดังนั้นแม้ว่า$(<&3)
จะไม่ได้รับการยอมรับว่าพิเศษ โอเปอเรเตอร์มันจะยังคงทำงานเหมือนเดิมksh
ด้วยการเรียกเพจเจอร์ให้ทำ (เพจเจอร์นั้นทำตัวเหมือนcat
ตั้งแต่ stdout จะเป็นไพพ์)
อย่างไรก็ตามในขณะที่ksh
's $(< a < b)
จะขยายไปยังเนื้อหาของa
ในzsh
จะขยายไปยังเนื้อหาของa
และb
(หรือเพียงแค่b
ถ้าmultios
ตัวเลือกที่ถูกปิดใช้งาน) $(< a > b)
จะคัดลอกa
ไปb
และขยายไปไม่มีอะไร ฯลฯ
bash
มีโอเปอเรเตอร์ที่คล้ายกัน แต่มีข้อแตกต่างเล็กน้อย:
อนุญาตความคิดเห็นก่อนหน้า แต่ไม่หลังจาก:
echo "$(
# getting the content of file
< file)"
ทำงานได้ แต่:
echo "$(< file
# getting the content of file
)"
ขยายไปสู่อะไร
เช่นเดียวกับในzsh
เพียงหนึ่งไฟล์เปลี่ยนเส้นทาง stdin แม้ว่าจะไม่มีฤดูใบไม้ร่วงกลับไป$READNULLCMD
เพื่อให้$(<&3)
, $(< a < b)
ไม่ดำเนินการเปลี่ยนเส้นทาง แต่ขยายไปยังไม่มีอะไร
- ด้วยเหตุผลบางอย่างในขณะที่
bash
ไม่ได้เรียกใช้cat
มันก็ยังคงดำเนินกระบวนการที่ฟีดเนื้อหาของไฟล์ผ่านไพพ์ทำให้การเพิ่มประสิทธิภาพน้อยกว่าเชลล์อื่น ๆ มันอยู่ในผลเหมือน$(cat < file)
ที่cat
จะ cat
builtin
- อันเป็นผลมาจากข้างต้นการเปลี่ยนแปลงใด ๆ ที่เกิดขึ้นภายในจะสูญหายไปในภายหลัง (ในตัวอย่างที่
$(<${file=foo.txt})
กล่าวถึงข้างต้นการ$file
มอบหมายนั้นหายไปในภายหลัง)
ในbash
, IFS= read -rd '' var < file
(ยังทำงานในzsh
) เป็นวิธีที่มีประสิทธิภาพมากขึ้นในการอ่านเนื้อหาในที่ข้อความไฟล์ลงในตัวแปร นอกจากนี้ยังมีประโยชน์ในการรักษาอักขระบรรทัดใหม่ที่ตามมา ดูเพิ่มเติม$mapfile[file]
ในzsh
(ในzsh/mapfile
โมดูลและสำหรับไฟล์ปกติเท่านั้น) ซึ่งใช้งานได้กับไฟล์ไบนารี
โปรดทราบว่าตัวแปรที่ใช้ pdksh ksh
มีความแตกต่างเล็กน้อยเมื่อเทียบกับ ksh93 ที่น่าสนใจในmksh
(หนึ่งในเชลล์ pdksh ที่ได้มา) ใน
var=$(<<'EOF'
That's multi-line
test with *all* sorts of "special"
characters
EOF
)
ถูกปรับให้เหมาะสมเมื่อเนื้อหาของเอกสาร here (ไม่มีตัวอักษรต่อท้าย) ถูกขยายโดยไม่มีไฟล์ชั่วคราวหรือไพพ์ที่ใช้งานเป็นอย่างอื่นในกรณีของเอกสาร here ซึ่งทำให้เป็นไวยากรณ์แบบหลายบรรทัดที่มีประสิทธิภาพ
ที่จะพกพาไปทุกรุ่นksh
, zsh
และbash
ที่ดีที่สุดคือการ จำกัด เพียง$(<file)
หลีกเลี่ยงการแสดงความคิดเห็นและแบริ่งในใจว่าการปรับเปลี่ยนตัวแปรภายในอาจจะหรืออาจไม่ได้รับการเก็บรักษาไว้
bash
จะตีความว่าเป็นcat filename
" คุณหมายถึงพฤติกรรมนี้เฉพาะกับการทดแทนคำสั่งหรือไม่? เพราะถ้าฉันวิ่ง< filename
ด้วยตัวเองทุบตีจะไม่ออกมา มันจะไม่ส่งผลอะไรและคืนฉันกลับสู่พรอมต์