ฉันต้องการต่อผลลัพธ์จาก echo กับเนื้อหาของไฟล์ ฉันได้ลองคำสั่งต่อไปนี้แล้ว:
echo "abc" | cat 1.txt > 2.txt
แต่ไฟล์มีเพียงเนื้อหาจาก2.txt 1.txtทำไมมันไม่ทำงาน
ฉันต้องการต่อผลลัพธ์จาก echo กับเนื้อหาของไฟล์ ฉันได้ลองคำสั่งต่อไปนี้แล้ว:
echo "abc" | cat 1.txt > 2.txt
แต่ไฟล์มีเพียงเนื้อหาจาก2.txt 1.txtทำไมมันไม่ทำงาน
คำตอบ:
ไม่ทำงานเนื่องจากcatโปรแกรมในลำดับไพพ์ของคุณไม่ได้รับคำสั่งให้อ่านechoเอาต์พุตของโปรแกรมจากอินพุตมาตรฐาน
คุณสามารถใช้เป็นชื่อไฟล์หลอกเพื่อแสดงการป้อนข้อมูลมาตรฐาน- catจากman catการติดตั้ง msys2:
EXAMPLES
cat f - g
Output f's contents, then standard input, then g's contents.
ลองดูสิ
echo "abc" | cat - 1.txt > 2.txt
แทน.
ตามที่ระบุไว้โดยผู้อื่นคำสั่งดั้งเดิมของคุณล้มเหลวเนื่องจากcat 1.txtไม่สนใจอินพุตมาตรฐาน ระบุว่าควรเป็นอาร์กิวเมนต์แรก ( cat - 1.txt) หรือใช้การเปลี่ยนเส้นทางบล็อกเพื่อเปลี่ยนเส้นทางecho abc และ cat 1.txtรวมกัน เพื่อปัญญา:
{ echo abc; cat 1.txt; } > 2.txt
ข้อความที่ตัดตอนมาที่เกี่ยวข้องจากคู่มือ ( man bash):
คำสั่งผสมคำสั่ง
ผสมเป็นหนึ่งในสิ่งต่อไปนี้ ในกรณีส่วนใหญ่รายการในคำอธิบายของคำสั่งอาจถูกแยกออกจากส่วนที่เหลือของคำสั่งโดยหนึ่งบรรทัดใหม่หรือมากกว่าและอาจตามมาด้วยบรรทัดใหม่แทนเซมิโคลอน
(รายการ)รายการจะถูกดำเนินการในสภาพแวดล้อม subshell (ดูสภาพแวดล้อมคำสั่งด้านล่าง) การกำหนดตัวแปรและคำสั่ง builtin ที่ส่งผลกระทบต่อสภาพแวดล้อมของเชลล์จะไม่มีผลบังคับใช้หลังจากคำสั่งเสร็จสิ้น สถานะการส่งคืนคือสถานะการออกของรายการ
{รายการ;}รายการถูกดำเนินการอย่างง่ายในสภาพแวดล้อมเชลล์ปัจจุบัน รายการจะต้องถูกยกเลิกด้วยการขึ้นบรรทัดใหม่หรืออัฒภาค นี้เป็นที่รู้จักกันเป็นคำสั่งกลุ่ม สถานะกลับเป็นสถานะออกจากรายการ โปรดทราบว่าแตกต่างจาก metacharacters
(และ),{และ}มีคำสงวนและจะต้องเกิดขึ้นที่คำสงวนได้รับอนุญาตให้ได้รับการยอมรับ เนื่องจากไม่ทำให้เกิดการแบ่งคำจึงต้องแยกออกจากรายการ ด้วยช่องว่างหรือเชลล์ตัวอักขระอื่น
ตัวเลือกแรก (สภาพแวดล้อม subshell) มีผลข้างเคียงมากมายส่วนใหญ่หากไม่ใช่ทั้งหมดที่ไม่เกี่ยวข้องกับสถานการณ์ของคุณ อย่างไรก็ตามหากการเปลี่ยนเส้นทางกลุ่มคำสั่งเป็นสิ่งที่คุณต้องการดังนั้นตัวเลือก # 2 ที่นี่ (คำสั่งกลุ่ม) เป็นที่ต้องการ
( echo "abc"; cat 1.txt ) > 2.txt
คุณไพพ์เอาต์พุต echo ไปที่ cat แต่ cat ไม่ได้ใช้อินพุตและละเว้น ตอนนี้คำสั่งจะรันทีละอันและเอาท์พุทของมันถูกจัดกลุ่ม (วงเล็บ) และนำไปสู่ 2.txt
bash(1)ถึงมันอธิบายถึงพฤติกรรมที่เชลล์ที่สอดคล้องกับ POSIXทุกคนต้องสนับสนุน
คำสั่งของคุณไม่ได้ทำอะไรกับการส่งออกของcat 1.txtecho "abc"
แต่
(echo "abc"; cat 1.txt) > 2.txt
จะเขียนผลลัพธ์ของทั้งสองคำสั่งลงใน 2.txt
ใน POSIX เชลล์คุณสามารถใช้การทดแทนคำสั่งเพื่อใช้cat fileเป็นอินพุตสำหรับecho:
echo $(cat file1.txt) "This Too"
ใน Bash คุณสามารถใช้การทดแทนกระบวนการและใช้ echo เป็น "ไฟล์" อื่นสำหรับcatเช่นใน:
cat file1.txt <(echo This Too)
จากนั้นไพพ์หรือเปลี่ยนทิศทางเอาต์พุตตามที่คุณเห็นว่าเหมาะสม
เช่นเดียวกับคำตอบอื่น ๆ ที่บอกว่า cat ไม่สนใจ stdin หากมีไฟล์ให้ดู (ฉันชอบคำตอบของ Daniel & mvw ด้วยเช่นกัน +1 สำหรับพวกเขา)
<(command)ก่อสร้างเป็นส่วนขยายทุบตี มันไม่ได้เป็น POSIX /bin/shดังนั้นคุณจึงไม่สามารถพึ่งพาได้ในสคริปต์ที่ควรจะได้รับการดำเนินการด้วย
แค่เดา แต่ดูเหมือนว่าคุณมีกระบวนการที่ทำซ้ำได้ซึ่งเป็นตัวเลือกที่ดีสำหรับนามแฝงหรือฟังก์ชัน นามแฝงมักเป็นทางลัดสำหรับการเรียกใช้คำสั่ง bash เช่นตัวย่อบนอินพุตสตรีมเดียวเป็นอาร์กิวเมนต์ / s
alias hg="history | grep"
อย่างไรก็ตามในกรณีนี้ฟังก์ชั่นจะสามารถอ่านได้ง่ายขึ้นเนื่องจากคุณกำลังรวมอินพุตหลายสตรีมแยก (2) และคำสั่ง bash หลายคำสั่ง คุณมีสองอาร์กิวเมนต์แรกคือสตริงและอีก filepath ในที่สุดคุณต้องการให้ผลลัพธ์ถูกเขียนลงในสตรีมเอาต์พุต stdout
จากพรอมต์ CLI ให้พิมพ์สิ่งนี้:
# ecat()
{
echo ${1}
cat ${2}
}
ฟังก์ชั่นของคุณชื่อ ecat ซึ่งเป็นที่น่าจดจำ
ตอนนี้คุณสามารถเรียกใช้เป็น
ecat "abc" 1.txt
หากต้องการต่อท้ายเพียงระบุปลายทางเอาต์พุตอื่นให้ stdout:
ecat "abc" 1.txt >> 2.txt
ผู้ประกอบการเปลี่ยนเส้นทางผนวก '>>' จะเพิ่มผลลัพธ์ไปยังจุดสิ้นสุดของไฟล์ที่ระบุ
หากคุณชอบให้ผนวกไฟล์ ~ / .bashrc ของคุณเพื่อใช้ซ้ำ
declare -f ecat >> ~/.bashrc
นั่นก็หมายความว่าคุณสามารถตกแต่ง ฯลฯ ภายในนิยามฟังก์ชั่นของคุณ
ควรป้องกันไฟล์จากการเขียนทับโดยการเพิ่มสิ่งนี้ลงใน ~ / .bashrc ของคุณ
set noclobber
"$1" "$2"ในบริบทนี้วงเล็บปีกกาไม่ได้ทำอะไรดี ดู${name}ไม่ได้หมายความว่าคุณคิดว่ามันจะ… .
noclobberข้อเสนอแนะที่ตอบสนองต่อคำถามที่อยู่ในมือ? (ฉันยังไม่มั่นใจมากว่ามันเป็นคำแนะนำที่ดี - การปรับเปลี่ยนพฤติกรรมทั่วโลกมีแนวโน้มที่จะทำลายสคริปต์ / คำแนะนำ / การปฏิบัติที่สร้างขึ้นโดยมีค่าเริ่มต้นในใจ)
รหัสต่อไปนี้จะใช้งานได้:
echo abc >> 1.txt && cat 1.txt > 2.txt
การส่งออกของ ก้อง abcจะถูกผนวกเข้ากับ 1.txt >> หลังจากนั้น&&จะบอกให้ทำงานชุดต่อไปของคำสั่งที่ประสงค์แมว 1.txtแล้วออกไปยัง2.txt โดยพื้นฐานแล้วมันจะผนวกเอาท์พุทของคำสั่งแรกลงใน 1.txt แล้วส่งเอาต์พุตของ 1.txt ไปเป็น 2.txt
หากคุณต้องการให้ abc ปรากฏก่อนคุณสามารถใช้รหัสต่อไปนี้:
echo abc >> 2.txt && cat 1.txt >> 2.txt
abcที่ด้านล่างของ2.txt; คำถามที่ต้องการมันอยู่ด้านบน (2) ปรับเปลี่ยน1.txtไฟล์ นี่เป็นสิ่งที่ยอมรับไม่ได้
echoก่อนที่catในคำสั่งตัวอย่างผมคิดว่ามันไม่ตรงอย่างชัดเจน ,บอกว่ามันต้องการผลลัพธ์จากก้องก่อนที่ เนื้อหาของไฟล์อินพุต ดูเหมือนว่าคนส่วนใหญ่ตีความอย่างนั้น (2) 1.txtเป็นไฟล์อินพุต 1.txtคำถามที่ไม่ได้พูดอะไรเกี่ยวกับการแก้ไข ความจริงที่ว่าไฟล์อินพุตไม่ควรถูกแก้ไขไปโดยไม่บอก
catอ่านจากอินพุตมาตรฐานเท่านั้นหากไม่มีข้อโต้แย้งชื่อไฟล์