วิธีต่อท้ายหลายบรรทัดในไฟล์


301

ฉันกำลังเขียนสคริปต์ทุบตีเพื่อค้นหาไฟล์หากไม่มีอยู่ให้สร้างและผนวกกับมัน:

Host localhost
    ForwardAgent yes

ดังนั้น"line then new line 'tab' then text"ฉันคิดว่ามันเป็นรูปแบบที่ละเอียดอ่อน ฉันรู้ว่าคุณสามารถทำได้:

cat temp.txt >> data.txt

แต่มันดูแปลก ๆ ตั้งแต่สองบรรทัด มีวิธีต่อท้ายที่ในรูปแบบนี้หรือไม่:

echo "hello" >> greetings.txt

คำตอบ:


526
# possibility 1:
echo "line 1" >> greetings.txt
echo "line 2" >> greetings.txt

# possibility 2:
echo "line 1
line 2" >> greetings.txt

# possibility 3:
cat <<EOT >> greetings.txt
line 1
line 2
EOT

หากจำเป็นต้องใช้ sudo (สิทธิ์ผู้ใช้อื่น) เพื่อเขียนไปยังไฟล์ให้ใช้สิ่งนี้:

# possibility 1:
echo "line 1" | sudo tee -a greetings.txt > /dev/null

# possibility 3:
sudo tee -a greetings.txt > /dev/null <<EOT
line 1
line 2
EOT

2
@TheLegend ที่เรียกว่า "เอกสารที่นี่" ดูที่ย่อหน้านั้นในหน้า man
Hauke ​​Laging

1
( echo "line 1" ; echo "line 2" ) >>greetings.txtหนึ่งเป็นไปได้มากขึ้นคือ
ott--

2
@ ott-- คุณไม่ต้องการ subshell จริง (เช่นสามารถบันทึกหนึ่งกระบวนการใหม่), ก็พอ:{ echo "line 1" ; echo "line 2"; } >>greetings.txt
Hauke ​​Laging

2
ความแตกต่างระหว่าง EOT และ EOL คืออะไร?
cikatomo

15
@cikatomo ในcat <<EOTการEOTเป็นเพียงสตริงสุ่ม อาจเป็นcat <<FOOเช่นกัน
Hauke ​​Laging

60
printf '%s\n    %s\n' 'Host localhost' 'ForwardAgent yes' >> file.txt

หรือหากเป็นแท็บตัวอักษรที่คุณต้องการ (แทนที่จะเป็นสี่ช่องว่างในคำถามของคุณ):

printf '%s\n\t%s\n' 'Host localhost' 'ForwardAgent yes' >> file.txt

คุณสามารถบรรลุผลเช่นเดียวกันด้วยechoแต่วิธีการที่แตกต่างจากการใช้งานเพื่อการใช้งานในขณะที่printfคงที่



16

อีกวิธีคือการใช้ tee

tee -a ~/.ssh/config << END
Host localhost
  ForwardAgent yes
END

เส้นเลือกสองสามบรรทัดจากteeหน้าคนของ:

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

-a - ผนวกเอาต์พุตไปยังไฟล์แทนที่จะเขียนทับมัน


6

SED สามารถผนวกบรรทัดต่อท้ายไฟล์เช่น:

sed -i '$ a text to be inserted' fileName.file
$เลือกจุดสิ้นสุดไฟล์, aบอกให้ผนวกและหลังจากนี้จะมีข้อความที่จะถูกแทรก แน่นอนว่าชื่อไฟล์


ที่มา: http://www.yourownlinux.com/2015/04/sed-command-in-linux-append-and-insert-lines-to-file.html

========== แก้ไข == ==========

วิธีการนี้มีประโยชน์เพิ่มเติมมากกว่าวิธีอื่นหรือไม่?
ใช่วิธีนี้มีประโยชน์เพิ่มเติมในการต่อท้ายไฟล์ใด ๆ ที่ส่งคืนในการค้นหาเช่นนี้ find . -name "*.html" -exec sed -i '$ a </html>' {} \;

ฉันใช้ตัวอย่างด้านบนเพื่อแทรกแท็ก html สิ้นสุดที่หายไปในทุกหน้า html ภายในจำนวนไดเรกทอรี

===================================


1
หากคุณจะแสดงไวยากรณ์สำหรับการผนวกหลายบรรทัดไปยังไฟล์ดังนั้นนี่จะเป็นคำตอบสำหรับคำถาม (แม้ว่าจะไม่เป็นประโยชน์มาก) คำตอบอื่น ๆ ทั้งหมดเพียงแค่เขียนข้อความใหม่ คำตอบนี้จะอ่านไฟล์ทั้งหมดและเขียนใหม่รวมถึงข้อความที่เพิ่มเข้ามา วิธีนี้มีประโยชน์มากกว่าคนอื่น ๆ หรือไม่?
G-Man

ใช้งานได้กับ GNU sedเท่านั้น BSD sedBails command a expects \ followed by textกับข้อผิดพลาด: ดังนั้นอย่าใช้สิ่งนี้เพื่อแก้ปัญหาที่เขียนไว้ในสคริปต์ มันมีแนวโน้มที่จะทำลาย (หรือทำอย่างถูกต้องเนื่องจากไวยากรณ์ที่ต้องการของ BSD นั้นรองรับ POSIX และจะทำงานกับ GNU ได้sedเช่นกัน
Wildcard

คำตอบอื่น ๆ สามารถใช้ได้findดังนี้: find . -name "*.txt" -exec sh -c 'printf "%s\n\t%s\n" "Host localhost" "ForwardAgent yes" >> "$1"' sh {} ";".
G-Man

1
นี่คือทางออกที่ดีมากเพราะมันไม่ได้ทำการเปลี่ยนเส้นทางกระแส ( >, >>) sudo echo 'something' > /fileและดังนั้นจึงไม่ประสบปัญหาของพวกเขาเช่นวิ่ง สำหรับฉันมันที่ดีที่สุดที่จะช่วยให้การผนวกสายไปยังแฟ้มในภาชนะ LXD lxc exec c sed -- '$ a newline' /myfileเช่นนั้น:
Draco Ater

การecho "a new line" >> foo.fileจะไม่สร้างบรรทัดใหม่เมื่อไฟล์ไม่ได้จบบรรทัดใหม่ แต่sed -i '$ a a new line' foo.fileจะทำเช่นsedนั้นดีกว่าโดยเฉพาะอย่างยิ่งคุณต้องการผนวกบรรทัดใหม่เข้ากับไฟล์เสมอ
โจวจิ

1

ฉันใช้ sed เพราะมันสามารถใช้กับ sudo ได้ ตัวอย่างเช่น:

sudo sed -i '$ a text to be inserted' fileName.file 

ทางเลือกน่าเกลียดมากเช่น:

sudo bash -c "echo a text to be inserted >> fileName.file"  

และแม้กระทั่งขี้เหร่เมื่อทำกับ ssh


1
ทำไมคำตอบนี้จึงลดลง? ดูเหมือนว่าโซลูชันที่ฉันต้องการ มีปัญหากับมันไหม? ถ้าไม่ฉันจะใช้มันแล้วโหวตขึ้น
MountainX

คุณsed -iไม่มีส่วนขยายเป็นอาร์กิวเมนต์หรือไม่ ตัวอย่างของคุณอาจมีพารามิเตอร์ที่ไม่ถูกต้อง
protometa

1

อีกหนึ่งซับคือ:

echo "Greetings 1" >> greetings.txt && echo "Greetings 2" >> greetings.txt

ฉันชอบความ-eคิดของตัวเลือกมากกว่าเพราะให้การควบคุมมากกว่านี้

echo -e "Greeting 1\nGreetings 2\n" >> greetings.txt

1

หนึ่งสามารถเลียนแบบcat >> out.txtด้วย Perl หรือ Python เพื่อให้ได้ผลเดียวกัน Perl:

perl -e 'open(fh,">>","./out.txt");while(<>){printf(fh "%s",$_)};close(fh);'

และ Python:

python -c 'import sys;f=open(sys.argv[1],"a");l=[i for i in sys.stdin];f.write("".join(l))' out.txt 

โปรดทราบว่าสำหรับไพ ธ อนคุณจะต้องกดCtrl+ Dสองครั้ง ดูคำถามที่เกี่ยวข้องกับ stackoverflowสำหรับข้อมูลเพิ่มเติม


1

นี่คือตัวอย่างการผนวกหลายบรรทัดในไฟล์:

{
        echo '  directory "/var/cache/bind";'
        echo '  listen-on { 127.0.0.1; };'
        echo '  listen-on-v6 { none; };'
        echo '  version "";'
        echo '  auth-nxdomain no;'
        echo '  forward only;'  
        echo '  forwarders { 8.8.8.8; 8.8.4.4; };'
        echo '  dnssec-enable no;'
        echo '  dnssec-validation no;'
} >> your_file.txt

0

นอกจากคำตอบหลักแล้วในกรณีที่ไฟล์ต้องการการอนุญาตจากผู้ใช้ขั้นสูงเพียงแค่เพิ่มsudoไว้ด้านหน้าechoจะไม่ทำงาน

นี่เป็นเพราะเชลล์แบ่งคำสั่งและแม้ว่าจะechoทำงานเป็นรูท แต่>>รันด้วยสิทธิ์ปกติ

สิ่งนี้จะใช้งานได้สำหรับผู้ใช้ระดับสูง: sudo su -c "echo 'Line 3' >> greetings.txt"


คุณไม่ต้องการที่suนี่ ( sudo suไม่ดี) แต่คุณถูกต้องที่คุณต้องการบางสิ่งบางอย่างจัดการการเปลี่ยนเส้นทางเชลล์; sudo sh -c "echo stuff >> file.txt"บางที ไม่มีการออมสุทธิ แต่เป็นการปฏิบัติที่ดีกว่า
roaima
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.