ใน Unix ผู้แก้ไขส่วนใหญ่ทำงานโดยสร้างไฟล์ชั่วคราวใหม่ที่มีเนื้อหาที่แก้ไข เมื่อบันทึกไฟล์ที่แก้ไขแล้วไฟล์ต้นฉบับจะถูกลบและไฟล์ชั่วคราวจะถูกเปลี่ยนชื่อเป็นชื่อเดิม (แน่นอนว่ามีมาตรการป้องกันต่าง ๆ เพื่อป้องกันดาต้าoss) ตัวอย่างเช่นรูปแบบที่ใช้โดยsed
หรือperl
เมื่อเรียกใช้ด้วยการ-i
ตั้งค่าสถานะ ("in-place") ซึ่งไม่ได้เป็น มันควรจะถูกเรียกว่า "สถานที่ใหม่ที่มีชื่อเก่า"
วิธีนี้ใช้งานได้ดีเพราะ unix มั่นใจ (อย่างน้อยสำหรับระบบไฟล์ในระบบ) ที่ไฟล์ที่เปิดอยู่ยังคงมีอยู่จนกว่าจะถูกปิดแม้ว่ามันจะ "ลบ" และไฟล์ใหม่ที่มีชื่อเดียวกันจะถูกสร้างขึ้น (ไม่ใช่เรื่องบังเอิญที่ระบบยูนิกซ์เรียกว่า "ลบ" ไฟล์จริงๆแล้วเรียกว่า "unlink") ดังนั้นโดยทั่วไปถ้าล่ามเชลล์มีไฟล์ต้นฉบับเปิดอยู่และคุณ "แก้ไข" ไฟล์ในลักษณะที่อธิบายไว้ข้างต้น เชลล์จะไม่เห็นการเปลี่ยนแปลงเนื่องจากมันยังคงเปิดไฟล์เดิมอยู่
[หมายเหตุ: เช่นเดียวกับความคิดเห็นตามมาตรฐานทั้งหมดข้างต้นอาจมีการตีความหลายครั้งและมีหลายกรณีเช่น NFS ยินดีต้อนรับคนเดินเท้าเพื่อกรอกความคิดเห็นด้วยข้อยกเว้น]
แน่นอนว่าเป็นไปได้ที่จะแก้ไขไฟล์โดยตรง มันไม่สะดวกสำหรับการแก้ไขเนื่องจากในขณะที่คุณสามารถเขียนทับข้อมูลในไฟล์คุณไม่สามารถลบหรือแทรกโดยไม่ต้องเลื่อนข้อมูลต่อไปนี้ทั้งหมดซึ่งจะเป็นการเขียนซ้ำมาก นอกจากนี้ในขณะที่คุณทำการขยับเนื้อหาของไฟล์จะไม่สามารถคาดการณ์ได้และกระบวนการที่เปิดไฟล์จะประสบ ในการที่จะหลีกเลี่ยงสิ่งนี้ (เช่นในระบบฐานข้อมูล) คุณจำเป็นต้องมีโปรโตคอลการดัดแปลงและล็อคแบบกระจาย สิ่งที่อยู่นอกเหนือขอบเขตของยูทิลิตี้การแก้ไขไฟล์ทั่วไป
ดังนั้นหากคุณต้องการแก้ไขไฟล์ในขณะที่กำลังประมวลผลโดยเชลล์คุณมีสองตัวเลือก:
คุณสามารถต่อท้ายไฟล์ สิ่งนี้ควรใช้งานได้เสมอ
คุณสามารถเขียนทับไฟล์ด้วยเนื้อหาใหม่ที่มีความยาวเท่ากัน สิ่งนี้อาจเป็นไปได้หรือไม่ขึ้นอยู่กับว่าเชลล์อ่านส่วนหนึ่งของไฟล์นั้นหรือไม่ เนื่องจากไฟล์ I / O ส่วนใหญ่เกี่ยวข้องกับการอ่านบัฟเฟอร์และเนื่องจากเชลล์ทั้งหมดที่ฉันรู้จักอ่านคำสั่งผสมทั้งหมดก่อนที่จะเรียกใช้งานมันไม่น่าเป็นไปได้เลยที่คุณจะได้รับสิ่งนี้ แน่นอนว่ามันจะไม่น่าเชื่อถือ
ฉันไม่รู้เกี่ยวกับถ้อยคำใด ๆ ในมาตรฐาน Posix ซึ่งจริง ๆ แล้วต้องการความเป็นไปได้ในการต่อท้ายไฟล์สคริปต์ขณะที่ไฟล์กำลังถูกประมวลผลดังนั้นจึงอาจไม่ทำงานกับเชลล์ที่สอดคล้องกับ Posix ทุกตัวซึ่งน้อยกว่าข้อเสนอปัจจุบันเกือบ และบางครั้ง -posix- เข้ากันได้เปลือก ดังนั้น YMMV แต่เท่าที่ฉันรู้มันทำงานได้อย่างน่าเชื่อถือด้วยการทุบตี
ตามหลักฐานแล้วนี่คือการดำเนินการ "วนฟรี" ของโปรแกรมเบียร์ที่น่าอับอาย 99 ขวดใน bash ซึ่งใช้dd
ในการเขียนทับและผนวก (การเขียนทับมีความปลอดภัยน่าจะเป็นเพราะมันทดแทนบรรทัดที่กำลังดำเนินอยู่ในปัจจุบันซึ่งเป็นบรรทัดสุดท้ายของ ไฟล์ที่มีความคิดเห็นที่มีความยาวเท่ากันฉันทำเพื่อให้ผลลัพธ์สุดท้ายสามารถดำเนินการได้โดยไม่ต้องมีการปรับเปลี่ยนพฤติกรรมด้วยตนเอง)
#!/bin/bash
if [[ $1 == reset ]]; then
printf "%s\n%-16s#\n" '####' 'next ${1:-99}' |
dd if=/dev/stdin of=$0 seek=$(grep -bom1 ^#### $0 | cut -f1 -d:) bs=1 2>/dev/null
exit
fi
step() {
s=s
one=one
case $beer in
2) beer=1; unset s;;
1) beer="No more"; one=it;;
"No more") beer=99; return 1;;
*) ((--beer));;
esac
}
next() {
step ${beer:=$(($1+1))}
refrain |
dd if=/dev/stdin of=$0 seek=$(grep -bom1 ^next\ $0 | cut -f1 -d:) bs=1 conv=notrunc 2>/dev/null
}
refrain() {
printf "%-17s\n" "# $beer bottles"
echo echo ${beer:-No more} bottle$s of beer on the wall, ${beer:-No more} bottle$s of beer.
if step; then
echo echo Take $one down, pass it around, $beer bottle$s of beer on the wall.
echo echo
echo next abcdefghijkl
else
echo echo Go to the store, buy some more, $beer bottle$s of beer on the wall.
fi
}
####
next ${1:-99} #