เนื่องจากคำถามนี้เป็นผลการค้นหาอันดับต้น ๆ ในเครื่องมือค้นหานี่คือหนึ่งซับอิงจากhttps://serverfault.com/a/547331ที่ใช้ subshell แทนsponge
(ซึ่งมักไม่ได้เป็นส่วนหนึ่งของการติดตั้งวานิลลาเช่น OS X) :
echo "$(grep -v 'seg[0-9]\{1,\}\.[0-9]\{1\}' file_name)" > file_name
กรณีทั่วไปคือ:
echo "$(cat file_name)" > file_name
แก้ไขวิธีแก้ปัญหาข้างต้นมีข้อแม้บางประการ:
printf '%s' <string>
ควรใช้แทนecho <string>
เพื่อให้ไฟล์ที่มี-n
ไม่ก่อให้เกิดพฤติกรรมที่ไม่ต้องการ
- แถบการแทนที่คำสั่งต่อท้ายบรรทัดใหม่ ( นี่คือบั๊ก / คุณสมบัติของเชลล์เช่น bash ) ดังนั้นเราควรต่อท้ายอักขระ postfix เช่น
x
เอาต์พุตและลบออกด้านนอกผ่านการขยายพารามิเตอร์ของตัวแปรชั่วคราวเช่น${v%x}
เช่น
- การใช้ตัวแปรชั่วคราวจะ
$v
เหยียบค่าของตัวแปรที่มีอยู่$v
ในสภาพแวดล้อมเชลล์ปัจจุบันดังนั้นเราควรซ้อนนิพจน์ทั้งหมดไว้ในวงเล็บเพื่อรักษาค่าก่อนหน้า
- ข้อผิดพลาด / คุณลักษณะอื่นของเชลล์เช่น bash คือการแทนที่คำสั่งจะแถบอักขระที่พิมพ์ไม่ได้เช่น
null
จากเอาต์พุต ฉันรับการตรวจสอบนี้โดยการโทรและการดูในฐานสิบหกด้วยdd if=/dev/zero bs=1 count=1 >> file_name
cat file_name | xxd -p
แต่echo $(cat file_name) | xxd -p
ถูกปล้น. ดังนั้นคำตอบนี้ควรไม่ได้นำไปใช้กับไฟล์ไบนารีหรืออะไรที่ใช้อักขระ unprintable เป็นลินช์ชี้ให้เห็น
วิธีแก้ปัญหาทั่วไป (อัลเบตช้าลงเล็กน้อยหน่วยความจำมากขึ้นและยังคงลอกอักขระที่พิมพ์ไม่ได้) คือ:
(v=$(cat file_name; printf x); printf '%s' ${v%x} > file_name)
ทดสอบจากhttps://askubuntu.com/a/752451 :
printf "hello\nworld\n" > file_uniquely_named.txt && for ((i=0; i<1000; i++)); do (v=$(cat file_uniquely_named.txt; printf x); printf '%s' ${v%x} > file_uniquely_named.txt); done; cat file_uniquely_named.txt; rm file_uniquely_named.txt
ควรพิมพ์:
hello
world
ในขณะที่เรียกcat file_uniquely_named.txt > file_uniquely_named.txt
ในเชลล์ปัจจุบัน:
printf "hello\nworld\n" > file_uniquely_named.txt && for ((i=0; i<1000; i++)); do cat file_uniquely_named.txt > file_uniquely_named.txt; done; cat file_uniquely_named.txt; rm file_uniquely_named.txt
พิมพ์สตริงว่าง
ฉันยังไม่ได้ทดสอบสิ่งนี้กับไฟล์ขนาดใหญ่ (อาจเกิน 2 หรือ 4 GB)
ฉันได้ยืมคำตอบนี้จากฮาร์ท Simhaและคอส