ต่อท้ายข้อความด้วย echo โดยไม่มีบรรทัดใหม่


15

echo "abc" >>file.txtฉันต้องการที่จะเพิ่มข้อความลงในไฟล์เช่น

แต่นี่เพิ่มabcหลังจากบรรทัดใหม่

ฉันจะเพิ่มabcท้ายไฟล์ด้วย echo โดยไม่มีบรรทัดใหม่ได้อย่างไร


2
ไฟล์นี้มีการขึ้นบรรทัดใหม่คุณเพียงแค่เพิ่มไฟล์ ดังนั้นคุณจะต้องแทนที่อักขระขึ้นบรรทัดใหม่จากบรรทัดสุดท้ายด้วย“ abc”
ctrl-alt-delor

ยินดีต้อนรับสู่ StackExchange! คำถามของคุณดี คงจะดีกว่าถ้าคุณระบุตัวอย่างเนื้อหาของไฟล์ของคุณ (ก่อนเพิ่มเติมสิ่งที่คุณได้รับหลังจากการเพิ่มสิ่งที่คุณต้องการแทน) ฉันพูดแบบนี้เพราะหนึ่งในคำตอบคือวิธีการเพิ่มabcโดยไม่ต้องขึ้นบรรทัดใหม่สุดท้ายซึ่ง (หลังจากอ่านคำถามของคุณอย่างตั้งใจ) ดูเหมือนจะไม่เป็นสิ่งที่คุณต้องการ
Law29

คำตอบ:


19

echo "abc" >>file.txtขึ้นบรรทัดใหม่หลังจาก abcไม่ใช่ก่อนหน้า ถ้าคุณจบลงด้วยการabcอยู่บนเส้นของตัวเองนั่นหมายความว่าการขึ้นบรรทัดใหม่ก่อนที่จะมีอยู่แล้วในปัจจุบันabcfile.txt

โปรดทราบว่ามันเป็นเรื่องปกติที่ไฟล์ข้อความจะสิ้นสุดในการขึ้นบรรทัดใหม่ บนยูนิกซ์บรรทัดประกอบด้วยลำดับอักขระอื่นที่ไม่ใช่null⁰หรือ newline ตามด้วย newline 1ดังนั้นไฟล์ข้อความที่ไม่ว่างจะลงท้ายด้วยอักขระบรรทัดใหม่

หากคุณต้องการเพิ่มข้อความในบรรทัดสุดท้ายของไฟล์คุณจะไม่สามารถทำได้>>เพราะจะต่อท้ายไฟล์เสมอดังนั้นมันจะเขียนทุกครั้งหลังขึ้นบรรทัดใหม่ แต่คุณต้องการเครื่องมือที่สามารถแก้ไขไฟล์ที่มีอยู่ได้ ตัวอย่างเช่นคุณสามารถใช้sed :

sed '$ s/$/abc/' file.txt >file.txt.new && mv file.txt.new file.txt

ในคำสั่ง sed คำสั่งแรก$หมายถึง“ ทำคำสั่งต่อไปนี้เฉพาะในบรรทัดสุดท้าย” คำสั่งs/REGEX/REPLACEMENT/จะแทนที่ REGEX ด้วย REPLACEMENT และนิพจน์ทั่วไปจะ$จับคู่ที่ส่วนท้ายของบรรทัด

คำสั่ง sed ของ Linux มีคุณสมบัติในตัวเพื่อสร้างลำดับไฟล์ใหม่และแทนที่โดยอัตโนมัติดังนั้นคุณจึงสามารถย่อให้สั้นลง

sed -i '$ s/$/abc/' file.txt

นั่นเป็นไบต์ที่ ASCII เรียกว่า NUL และ Unicode เรียก U + 0000 โปรแกรมประมวลผลข้อความอาจมีหรือไม่มีอักขระนี้ก็ได้
1 ดูคำจำกัดความของไฟล์ข้อความ , บรรทัดและอักขระขึ้นบรรทัดใหม่ในส่วน "คำจำกัดความ" ของบทนิยามฐานของ IEEE 1003.1-2008: 2016


2
ย่อหน้าที่สองของคุณหมายถึงการบ่งบอกว่าไฟล์ที่ไม่ได้ลงท้ายด้วยการขึ้นบรรทัดใหม่ไม่ใช่ไฟล์ข้อความหรือไม่? เช่นถ้าฉันใช้ไฟล์ข้อความ ASCII ที่มีอยู่ซึ่งลงท้ายด้วยบรรทัดใหม่และต่อท้ายหนึ่งไบต์0x41(ASCII 'A') แล้วในทางเทคนิคแล้วมันไม่ใช่ไฟล์ข้อความอีกต่อไปใช่ไหม? ถ้าเป็นเช่นนั้นฉันขอแนะนำให้เน้นจุดนั้นเพราะมันเป็นคำจำกัดความที่ไม่เข้าใจง่าย ถ้าไม่มีการเปลี่ยนแปลงเล็กน้อยในถ้อยคำอาจช่วยหลีกเลี่ยงความสับสน
David Z

2
@DavidZ: นั่นคือคำจำกัดความมาตรฐานของไฟล์ข้อความใน Unixland IIRC มันยังอยู่ใน POSIX ที่ไหนซักแห่ง
เควิน

1
@ Kevin ที่น่าสนใจฉันไม่เคยได้ยินมาก่อน ถึงแม้ว่ามันจะเป็นมาตรฐานฉันก็คิดว่ามันใช้งานง่าย
David Z

15

ฉันไม่คิดว่ามันเป็นไปได้ด้วยechoคำสั่งใช้sedวิธีการต่อไปนี้แทน:

sed -i '$ s/$/abc/' file.txt
  • -i- ปรับเปลี่ยนไฟล์inplace
  • $ - ระบุบันทึก / บรรทัดสุดท้าย
  • s/$/abc/- แทนส่วนท้ายของบรรทัด$ด้วยสตริงย่อยabc(สำหรับระเบียนสุดท้าย)

2
โปรดทราบว่า "ในสถานที่" ไม่ได้หมายถึงสถานที่จริง ๆ มันหมายถึง "เขียนเนื้อหาที่แก้ไขแล้วไปยังไฟล์ที่มีชื่อชั่วคราวข้างไฟล์ที่มีอยู่แล้วแทนที่มัน" คุณสามารถพิสูจน์ได้โดยดูที่ inodes ด้วยdate >file; ls -i file; sed -i 's/201/ZZZ/' file; ls -i file
roaima

@roaima ฉันรู้เกี่ยวกับการเปลี่ยนแปลงหมายเลข inode ของ sed
RomanPerekhrest

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

@roaima, กลางคืนคิดว่า -> อาจจะคิดว่า ...
RomanPerekhrest

ถ้าฉันต้องการแทนที่ abc ด้วยตัวแปร ใช้'$ s/$/$1/'ภาพพิมพ์$1
Florian Castelain

14

สมมติว่าไฟล์ยังไม่สิ้นสุดในบรรทัดใหม่และคุณเพียงต้องการผนวกข้อความเพิ่มเติมโดยไม่ต้องเพิ่มอีกคุณสามารถใช้-nอาร์กิวเมนต์เช่น

echo -n "some text here" >> file.txt

อย่างไรก็ตามระบบ UNIX บางระบบไม่มีตัวเลือกนี้ หากเป็นกรณีที่คุณสามารถใช้printfเช่น

printf %s "some text here" >> file.txt

( %sอาร์กิวเมนต์เริ่มต้นคือการป้องกันข้อความเพิ่มเติมที่มี%การจัดรูปแบบอักขระในนั้น)

จากman echo(ใน macOS High Sierra):

-n

อย่าพิมพ์อักขระขึ้นบรรทัดใหม่ที่ต่อท้าย สิ่งนี้อาจทำได้โดยการต่อ'\c'ท้ายสตริงเช่นเดียวกับที่ทำโดยระบบที่เข้ากันได้กับ iBCS2 โปรดทราบว่าตัวเลือกนี้รวมถึงผลกระทบของ'\c'การใช้งานจะถูกกำหนดใน IEEE Std 1003.1-2001 ("POSIX.1") ตามที่แก้ไขโดย Cor 1-2002 แอปพลิเคชันที่มีจุดประสงค์เพื่อความสะดวกในการพกพาสูงสุดขอแนะนำให้ใช้printf(1)เพื่อยับยั้งอักขระขึ้นบรรทัดใหม่


เห็นได้ชัดว่ามันค่อนข้างจะจบลงด้วยการขึ้นบรรทัดใหม่ echo -nจะไม่มีการขึ้นบรรทัดใหม่ในตอนท้ายabcแต่abcจะยังคงมีการขึ้นบรรทัดใหม่ซึ่งเป็นสิ่งที่ผู้ใช้ต้องการหลีกเลี่ยง
Kusalananda

@ Kusalananda คำตอบของฉันถูกเพิ่มเติมโดยใช้ข้อสันนิษฐานว่า OP จะพยายามเปลี่ยนกระบวนการของพวกเขาเช่นที่ปลอม\nไม่ปรากฏขึ้นในตอนแรก ตัวเลือกเพิ่มเติมจะดีกว่าโดยเฉพาะอย่างยิ่งเมื่อพวกเขาไม่ต้องเขียนไฟล์ใหม่ทุกครั้งที่มีการเปลี่ยนแปลง (ซึ่งอาจทำให้ช้าลงและทำงานในเวลาพหุนามหากทำซ้ำ)
ปุย

9

หากคุณมีtruncateคำสั่งและไฟล์ข้อความของคุณมี NL เป็นตัวอักษรตัวสุดท้ายคุณสามารถลบออกได้และต่อท้ายข้อความของคุณดังนี้:

truncate --size -1 file.txt
echo "abc" >>file.txt

(โปรดทราบว่าtruncateไม่สนใจเนื้อหาไฟล์และในตัวอย่างนี้จะลดขนาดไฟล์ลงหนึ่งไบต์ถ้าอักขระสุดท้ายของคุณไม่ใช่ไบต์เดียวนั่นคืออักขระ "กว้าง" แบบหลายไบต์คุณจะนำความเสียหายมาใช้)


5

สิ่งที่คุณต้องการคือการเพิ่มที่ส่วนท้ายของบรรทัดสุดท้ายดังนั้นก่อนที่ตัวคั่นของบรรทัดสุดท้ายนั้นดังนั้นก่อนอักขระตัวสุดท้ายของไฟล์

ด้วยksh93คุณสามารถทำสิ่งต่อไปนี้

echo abc 1<> file >#((EOF - 1))

1<>ตัวดำเนินการมาตรฐานอยู่ที่ไหนเพื่อเปิดไฟล์ในโหมดอ่าน + เขียน (และที่สำคัญกว่าโดยไม่มีการตัดปลาย ) บน stdout และ>#((...))เป็นตัวดำเนินการค้นหาเฉพาะ ksh93 (ที่นี่เพื่อค้นหาก่อนไบต์สุดท้าย) โปรดทราบว่าechoเขียนabc<newline>โดยที่การaแทนที่บรรทัดใหม่ที่อยู่ที่นั่นและechoเพิ่มขึ้นบรรทัดใหม่ของตัวเอง

zshเทียบเท่า:

zmodload zsh/system
{sysseek -w end -u 1 -1 && echo abc} 1<> file

แม้ว่าจะเทียบเท่าที่แน่นอนยิ่งขึ้นคุณต้องพิมพ์ข้อความแสดงข้อผิดพลาดเมื่อไม่สามารถค้นหาได้:

zmodload zsh/system
if sysseek -w end -u 1 -1; then
  echo abc
else
  syserror -p "$0: $LINENO: seek: "
fi 1<> file

-1

อาจเป็นUUOCแต่คุณสามารถทำได้:

echo "$(cat file.txt)abc" >file.txt

เมื่อ Gilles ชี้ให้เห็นคำสั่งนี้มีข้อ จำกัด :

ส่วนใหญ่ใช้งานได้ แต่ไม่ใช่ถ้ามีบางครั้งบรรทัดว่างที่ท้ายไฟล์และบรรทัดว่างทันทีก่อน เช่นไฟล์ที่มีจำนวนบรรทัดคงที่โดยที่บรรทัดสุดท้ายว่างเปล่าตอนแรกและถูกขยายเมื่อเวลาผ่านไปและบางครั้งบรรทัดถัดไปถึงบรรทัดสุดท้ายอาจว่างเปล่า

นอกจากนี้ระวังการใช้catไฟล์ที่คุณไม่คุ้นเคย:

สรุป :

ใช้sed


2
ส่วนใหญ่ใช้งานได้ แต่ไม่ใช่ถ้ามีบางครั้งบรรทัดว่างที่ท้ายไฟล์และบรรทัดว่างทันทีก่อน เช่นไฟล์ที่มีจำนวนบรรทัดคงที่โดยที่บรรทัดสุดท้ายว่างเปล่าตอนแรกและถูกขยายเมื่อเวลาผ่านไปและบางครั้งบรรทัดถัดไปถึงบรรทัดสุดท้ายอาจว่างเปล่า
Gilles 'หยุดความชั่วร้าย'

ฉันควรลบหรือไม่ ฉันคิดว่า Roman / คำตอบของคุณเป็นวิธีที่เหมาะสม แต่ฉันรู้ว่าฉันชอบเห็นทางเลือกและ OP ได้ขอecho: p
jesse_b

1
นอกจากนี้ยังทำให้ไฟล์ทั้งหมดอยู่ในบรรทัดคำสั่ง
n.caillou

@ n.caillou ฮะเหรอ? สิ่งนี้จะไม่พิมพ์อะไรไปยัง STDOUT
jesse_b

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