การเปลี่ยนเส้นทางเนื้อหาของไฟล์ไปยังคำสั่ง“ echo”


41

ฉันมีไฟล์ชื่อที่มีเนื้อหาเป็นเพียงสตริงmy_file.txt Helloฉันจะเปลี่ยนเส้นทางเนื้อหาไปยังคำสั่งได้echoอย่างไร

ฉันรู้ว่าฉันมีคำสั่งless, cat, more... echoแต่ฉันต้องทำมันด้วย

ฉันลองสิ่งนี้:

$ cat my_file.txt | echo

และสิ่งนี้:

$ echo < my_file.txt

แต่ในทั้งสองกรณีจะปรากฏเพียงช่องว่างใน stdout ไม่ใช่เนื้อหาของ my_file.txt

ฉันจะทำสิ่งนั้นได้อย่างไร


7
ทำไมคุณถึงยืนยันที่จะใช้echo?
เควิน

7
@Kevin ในที่สุดเขาก็ต้องการขยายลำดับการหลบหนีของ ANSI C ( \n, b... ) ในไฟล์ซึ่งจะเป็นการใช้งานที่ถูกต้องของecho(อย่างน้อยมาตรฐานecho) หรือสมมุติว่าเขาต้องการเข้าใจว่าทำไมมันไม่ทำงานอย่างนั้น ไม่ว่าในกรณีใดก็ตามไม่มีเหตุผลในการลงคะแนน IMO
Stéphane Chazelas

3
ฉันมาที่นี่เพราะฉันอยากรู้ว่าทำไมมันไม่ทำงานเมื่อฉันทำ echo <file.txt ดูเหมือนว่าคำถามที่สมเหตุสมผลที่ SE มีคำตอบนั้นมีประโยชน์มาก +1 จากฉัน
เซลล์ประสาท

คำตอบ:


53

คุณสามารถเปลี่ยนเส้นทางทั้งหมดที่คุณต้องการ echoแต่มันจะไม่ทำอะไรกับมัน echoไม่อ่านอินพุตมาตรฐาน สิ่งที่มันทำคือเขียนไปยังเอาต์พุตมาตรฐานอาร์กิวเมนต์ของมันคั่นด้วยอักขระช่องว่างและยกเลิกโดยอักขระบรรทัดใหม่ (และมีechoการใช้งานบางอย่างที่มีลำดับ escape บางอย่างในพวกเขาขยายและ / หรืออาร์กิวเมนต์เริ่มต้นด้วย-ถือว่าเป็นตัวเลือก)

หากคุณต้องการที่จะแสดงเนื้อหาของไฟล์ที่คุณต้องผ่านเนื้อหาที่เป็นอาร์กิวเมนต์ไปยังecho echoสิ่งที่ต้องการ:

echo "$(cat my_file.txt)"

โปรดทราบว่า$(...)แถบตัวอักษรต่อท้ายบรรทัดใหม่sจากการแสดงผลของการที่catคำสั่งและechoเพิ่มหนึ่งกลับ

นอกจากนี้โปรดทราบว่ายกเว้นด้วยzshคุณจะไม่สามารถส่งผ่านอักขระ NUL ในอาร์กิวเมนต์ของคำสั่งดังนั้นโดยทั่วไปจะไม่สามารถทำงานกับไฟล์ไบนารีได้ yashจะลบไบต์ที่ไม่ได้เป็นส่วนหนึ่งของอักขระที่ถูกต้องด้วย

ถ้าเหตุผลเพื่อต้องการที่จะทำเช่นนั้นเป็นเพราะคุณต้องการechoที่จะขยาย\n, \b, \0351... ลำดับหนีในแฟ้ม (เป็น UNIX ที่สอดคล้องกับechoการใช้งานที่ทำแต่ไม่ทั้งหมด ) แล้วคุณอยากจะใช้printfแทน :

printf '%b\n' "$(cat my_file.txt)"

ตรงกันข้ามกับที่หนึ่งเป็นแบบพกพาและจะไม่ได้มีปัญหาหากเนื้อหาของแฟ้มเริ่มต้นด้วยecho-


เป็นทางเลือกให้$(cat file), กับksh, zshและbash$(<file)หนึ่งยังสามารถทำได้: นั่นเป็นโอเปอเรเตอร์พิเศษที่เชลล์ทำการcatอ่านเนื้อหาของไฟล์เพื่อทำการขยายตัว มันก็ยังคงแถบบรรทัดใหม่ต่อท้ายและฉายาใน NUL zshไบต์ยกเว้นใน ในbashที่ยังคงมีกระบวนการพิเศษ โปรดทราบว่าข้อแตกต่างอย่างหนึ่งคือคุณจะไม่ได้รับข้อผิดพลาดใด ๆ หากพยายามอ่านไฟล์ประเภทไดเรกทอรีด้วยวิธีดังกล่าว นอกจากนี้ในขณะที่$(< file)พิเศษ$(< file; other command)ไม่ได้ (ในzshเมื่อไม่เลียนแบบเชลล์อื่น ๆ ที่จะยังคงขยายเนื้อหาของfile, โดยการรันคำสั่งโดยนัย $READNULLCMD (โดยทั่วไปคือเพจเจอร์))


3
ทั้งทุบตีและ zsh คุณสามารถข้ามและมีเพียงเปลือกอ่านได้โดยตรง:cat echo "$(<my_file.txt)"
เควิน

1
ใช่ด้วยksh , zshและbashคุณสามารถ$(<filename)ใช้ได้
Dimitre Radoulov

ขอบคุณมากนั่นคือสิ่งที่ฉันต้องการและใช้งานได้! :-)
danielmbcn

@Kevin, Dimitre เพิ่มแล้ว
Stéphane Chazelas

4

เมื่อเพิ่มคำตอบอื่นคุณสามารถลองเปลี่ยนเส้นทางอินพุตแทน cat

echo $(<my_file.txt)

หรือ

echo `<my_file.txt`

$()และ `` ดำเนินการสิ่งเดียวกันพวกเขาเรียกใช้คำสั่งภายในขอบเขตของพวกเขาและส่งออกไปยังเปลือกราวกับว่ามันได้รับเป็นอินพุตโดยผู้ใช้ ข้อแตกต่างระหว่างสองสิ่งนี้คือ $ () สามารถเรียกซ้ำและ `` ไม่สามารถเรียกซ้ำได้


2

คำตอบง่ายๆ: คุณทำไม่ได้ echo(ไม่ว่าจะเป็นเชลล์ในตัวหรือไบนารีปกติ) ไม่ได้ประมวลผลอินพุตมาตรฐาน - มันเป็นเพียงวิธีเดียวเท่านั้น


คำถามคือทำไมคุณต้องการทำเช่นนี้?
peterph

2

ตามที่กล่าวไว้

หากคุณต้องการechoแสดงเนื้อหาของไฟล์คุณจะต้องผ่านเนื้อหานั้นเป็นอาร์กิวเมนต์echo

ตัวอย่างเช่นคุณสามารถทำสิ่งนี้ได้ด้วยxargs(เนื่องจากคุณต้องเปิดใช้การตีความเครื่องหมายทับขวา ):

$ cat my_file.txt | xargs echo -e

หรือเพียงแค่สิ่งที่คุณถาม (โดยไม่ต้องตีความลำดับหนี ):

$ cat my_file.txt | xargs echo

อย่างไรก็ตามโปรดทราบว่าเมื่อใช้xargs echo(เช่นเดียวกับxargsbtw เป็นechoคำสั่งเริ่มต้น) มันเป็นechoคำสั่งจากระบบไฟล์ที่จะทำงานไม่ใช่echoคำสั่งbuiltin ของเชลล์ นอกจากนี้โปรดทราบว่าxargsคาดว่าอินพุตจะอยู่ในรูปแบบที่เฉพาะเจาะจงมาก (โดยที่ช่องว่าง, บรรทัดใหม่, ราคา, แบ็กสแลชมีความหมายพิเศษ) catไม่ได้ทำให้ความรู้สึกมากที่นี่มีเพียงหนึ่งไฟล์ concatenate (เช่นเดียวกับ< file.txt xargs echoทราบว่า Unix สอดคล้อง. echos ทำขยายตัวหลบหนีทับขวาโดยค่าเริ่มต้นและผลผลิต-eเมื่อecho -e.
Stéphane Chazelas

0

ในทุบตีควรทำสิ่งต่อไปนี้ด้วย:

echo `cat my_file.txt`

ส่วนใน backticks จะถูกแทนที่ด้วยผลลัพธ์ของคำสั่งนั้นคือในกรณีนี้ถูกแทนที่ด้วยเนื้อหาไฟล์


จริง ๆ แล้ว backticks ก็ทำงานเหมือน$( . . . )กัน คนที่ใช้งาน$()มักจะชอบพวกเขาเพราะคุณสามารถซ้อนมันได้ คำถามนี้เก่า แต่ก็พอใจมากกว่าที่จะตอบคำถามที่ยังไม่ได้ตอบ!
กฎหมาย

ไม่มาก มีความแตกต่างที่ลึกซึ้ง เมื่อใช้แบบฟอร์มย้อนหลังเห็บเครื่องหมายทับขวาจะคงความหมายตามตัวอักษรยกเว้นเมื่อตามด้วย $, `หรือ \ back-tick แรกที่ไม่ได้นำหน้าด้วย backslash จะยุติคำสั่ง เมื่อใช้แบบฟอร์ม $ (,,,) ตัวละครทั้งหมดระหว่างวงเล็บประกอบคำสั่ง
fpmurphy

เนื่องจากการแทนที่คำสั่งนั้นไม่ได้ยกมาตัวดำเนินการ split + glob จะถูกนำไปใช้กับมัน ตัวอย่างเช่นถ้าmy_file.txtมี*ที่จะพิมพ์รายชื่อไฟล์ในไดเรกทอรีปัจจุบัน
Stéphane Chazelas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.