คำสั่ง Cat และเสียงสะท้อน


14

ฉันต้องการต่อผลลัพธ์จาก echo กับเนื้อหาของไฟล์ ฉันได้ลองคำสั่งต่อไปนี้แล้ว:

echo "abc" | cat 1.txt > 2.txt

แต่ไฟล์มีเพียงเนื้อหาจาก2.txt 1.txtทำไมมันไม่ทำงาน


3
โปรแกรมเช่นcatอ่านจากอินพุตมาตรฐานเท่านั้นหากไม่มีข้อโต้แย้งชื่อไฟล์
Barmar

คำตอบ:


23

ไม่ทำงานเนื่องจาก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

แทน.


21

ตามที่ระบุไว้โดยผู้อื่นคำสั่งดั้งเดิมของคุณล้มเหลวเนื่องจาก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 ที่นี่ (คำสั่งกลุ่ม) เป็นที่ต้องการ


7
( echo "abc"; cat 1.txt ) > 2.txt

คุณไพพ์เอาต์พุต echo ไปที่ cat แต่ cat ไม่ได้ใช้อินพุตและละเว้น ตอนนี้คำสั่งจะรันทีละอันและเอาท์พุทของมันถูกจัดกลุ่ม (วงเล็บ) และนำไปสู่ ​​2.txt


1
คำตอบนี้สามารถปรับปรุงได้โดยอธิบายว่ามันทำงานอย่างไรและทำไมความพยายามดั้งเดิมของ OP ไม่ทำงาน
Bob

ตกลงลองดูสิ
เจอราร์ดเอช. ปิลล์

5
ไม่จำเป็นต้องระบุเชลล์ย่อยในที่นี้อย่างแน่นอนบางทีอาจเป็นการดีกว่าถ้าใช้คำสั่งกลุ่ม ดูคำตอบของฉันสำหรับรายละเอียดเพิ่มเติม
Nubarke

อ่า แต่ฉันไม่เคยใช้ทุบตี
เจอราร์ดเอช. ปิลล์

1
@ GerardH.Pille: ในขณะที่คำตอบของ Danielพูดbash(1)ถึงมันอธิบายถึงพฤติกรรมที่เชลล์ที่สอดคล้องกับ POSIXทุกคนต้องสนับสนุน
G-Man กล่าวว่า 'Reinstate Monica'

2

คำสั่งของคุณไม่ได้ทำอะไรกับการส่งออกของcat 1.txtecho "abc"

แต่ (echo "abc"; cat 1.txt) > 2.txt จะเขียนผลลัพธ์ของทั้งสองคำสั่งลงใน 2.txt


คำตอบนี้สามารถปรับปรุงได้โดยอธิบายว่าทางเลือกที่แนะนำนั้นทำงานอย่างไร
Bob

1

ใน POSIX เชลล์คุณสามารถใช้การทดแทนคำสั่งเพื่อใช้cat fileเป็นอินพุตสำหรับecho:

echo $(cat file1.txt) "This Too"

ใน Bash คุณสามารถใช้การทดแทนกระบวนการและใช้ echo เป็น "ไฟล์" อื่นสำหรับcatเช่นใน:

cat file1.txt <(echo This Too)

จากนั้นไพพ์หรือเปลี่ยนทิศทางเอาต์พุตตามที่คุณเห็นว่าเหมาะสม

เช่นเดียวกับคำตอบอื่น ๆ ที่บอกว่า cat ไม่สนใจ stdin หากมีไฟล์ให้ดู (ฉันชอบคำตอบของ Daniel & mvw ด้วยเช่นกัน +1 สำหรับพวกเขา)


1
คำตอบนี้สามารถปรับปรุงได้โดยอธิบายว่าเหตุใดความพยายามดั้งเดิมของ OP จึงไม่ทำงาน (และทำไมจึงจำเป็นต้องใช้แทน)
Bob

1
การ<(command)ก่อสร้างเป็นส่วนขยายทุบตี มันไม่ได้เป็น POSIX /bin/shดังนั้นคุณจึงไม่สามารถพึ่งพาได้ในสคริปต์ที่ควรจะได้รับการดำเนินการด้วย
Rhialto สนับสนุน Monica

0

แค่เดา ​​แต่ดูเหมือนว่าคุณมีกระบวนการที่ทำซ้ำได้ซึ่งเป็นตัวเลือกที่ดีสำหรับนามแฝงหรือฟังก์ชัน นามแฝงมักเป็นทางลัดสำหรับการเรียกใช้คำสั่ง 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

2
สำหรับฟังก์ชั่นของคุณทำงานได้อย่างถูกต้องคุณควรใช้และ"$1" "$2"ในบริบทนี้วงเล็บปีกกาไม่ได้ทำอะไรดี ดู${name}ไม่ได้หมายความว่าคุณคิดว่ามันจะ… .
G-Man กล่าวว่า 'Reinstate Monica'

1
วิธีการคือnoclobberข้อเสนอแนะที่ตอบสนองต่อคำถามที่อยู่ในมือ? (ฉันยังไม่มั่นใจมากว่ามันเป็นคำแนะนำที่ดี - การปรับเปลี่ยนพฤติกรรมทั่วโลกมีแนวโน้มที่จะทำลายสคริปต์ / คำแนะนำ / การปฏิบัติที่สร้างขึ้นโดยมีค่าเริ่มต้นในใจ)
Charles Duffy

0

รหัสต่อไปนี้จะใช้งานได้:

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

1
จะ (1) ใส่abcที่ด้านล่างของ2.txt; คำถามที่ต้องการมันอยู่ด้านบน (2)  ปรับเปลี่ยน1.txtไฟล์ นี่เป็นสิ่งที่ยอมรับไม่ได้
G-Man กล่าวว่า 'Reinstate Monica'

มันบอกว่าที่ไหน Ringger81 ไม่เคยระบุว่าใน 2.txt เขาต้องการให้ abc ปรากฏ คุณกำลังสมมติว่าสิ่งต่าง ๆ ที่คำถามไม่เคยพูด
Nasir Riley

(1) ตกลงคุณเพิ่มคะแนนที่ถูกต้องใน # 1 ขณะที่คำถามที่ระบุว่า“เอาท์พุทจากก้อง” ก่อน“เนื้อหาของไฟล์” ในข้อความแล้วทำให้echoก่อนที่catในคำสั่งตัวอย่างผมคิดว่ามันไม่ตรงอย่างชัดเจน ,บอกว่ามันต้องการผลลัพธ์จากก้องก่อนที่ เนื้อหาของไฟล์อินพุต ดูเหมือนว่าคนส่วนใหญ่ตีความอย่างนั้น (2)  1.txtเป็นไฟล์อินพุต 1.txtคำถามที่ไม่ได้พูดอะไรเกี่ยวกับการแก้ไข ความจริงที่ว่าไฟล์อินพุตไม่ควรถูกแก้ไขไปโดยไม่บอก
G-Man กล่าวว่า 'Reinstate Monica'

ฉันเข้าใจจุดของคุณเกี่ยวกับการไม่แก้ไขไฟล์ imput โค้ดที่สองของฉันจะได้ผลตามที่ต้องการโดยไม่ต้องทำเช่นนั้น
Nasir Riley

1
การเปิดไฟล์ต่อท้ายปิดปิดเปิดอีกครั้งต่อท้ายอีกครั้ง ... ทำไมทำอย่างนั้นแทนที่จะเปิดเพียงครั้งเดียวและเก็บการเปลี่ยนเส้นทางไว้สำหรับการดำเนินการทั้งสอง
Charles Duffy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.