Unix'te çoğu düzenleyici, düzenlenmiş içerikleri içeren yeni bir geçici dosya oluşturarak çalışır. Düzenlenen dosya kaydedildiğinde, orijinal dosya silinir ve geçici dosyaya orijinal adı verilir. (Elbette, veri kaybını önlemek için çeşitli güvenlik önlemleri vardır.) Bu, örneğin, "hiç yerinde" olmayan , ("yerinde") bayrağıyla kullanıldığında sed
veya kullanıldığında kullanılan stildir . Adı "eski adıyla yeni yer" olmalıydı.perl
-i
Bu iyi çalışır çünkü unix (en azından yerel dosya sistemleri için) açılmış bir dosyanın, "silinmiş" olsa ve aynı ada sahip yeni bir dosya oluşturulmuş olsa bile kapanana kadar varlığını sürdürdüğünü garanti eder. (Unix sisteminin bir dosyayı "silmek" aslında "unlink" olarak adlandırılması anlamına gelmez.) Bu nedenle, genel olarak konuşursak, eğer bir kabuk yorumlayıcısının açık bir kaynak dosyası varsa ve dosyayı yukarıda açıklanan şekilde "düzenlersiniz". orijinal dosya hala açık olduğundan, kabuk değişiklikleri bile görmez.
[Not: Tüm standartlara dayalı yorumlarda olduğu gibi, yukarıdakiler birden fazla yoruma tabidir ve NFS gibi çeşitli köşe davaları vardır. Anlaşmalar, yorumları istisnalar dışında doldurabilir.]
Elbette, dosyaları doğrudan değiştirmek mümkündür; bu sadece düzenleme amaçları için uygun değildir, çünkü bir dosyadaki verilerin üzerine yazarken, aşağıdaki tüm verileri değiştirmeden silemez veya ekleyemezsiniz, bu da çok fazla yeniden yazma anlamına gelir. Dahası, bu değişimi yaparken, dosyanın içeriği tahmin edilemez ve dosyayı açmış olan işlemler zarar görür. Bundan kurtulmak için (örneğin, veritabanı sistemlerinde olduğu gibi), gelişmiş bir değişiklik protokolleri kümesine ve dağıtılmış kilitlere ihtiyacınız vardır; Tipik bir dosya düzenleme programının kapsamı dışında kalan şeyler.
Bu nedenle, bir dosyayı kabuk tarafından işlenirken düzenlemek istiyorsanız, iki seçeneğiniz vardır:
Dosyaya ekleyebilirsiniz. Bu her zaman çalışması gerekir.
Aynı uzunluktaki yeni içeriklerle dosyanın üzerine yazabilirsiniz . Bu, kabuğun dosyanın o bölümünü okumuş olup olmamasına bağlı olarak çalışmayabilir veya çalışmayabilir. Çoğu dosya giriş / çıkış dosyası okuma arabellekleri içerdiğinden ve bildiğim tüm kabuklar çalıştırılmadan önce bir bileşik komutun tamamını okuduğundan, bununla başa çıkmanız pek mümkün değildir. Kesinlikle güvenilir olmazdı.
Posix standardında, dosya yürütülürken aslında bir komut dosyasına ekleme olanağı gerektiren herhangi bir ifade bilmiyorum, bu yüzden neredeyse tüm mevcut tekliflerle çok daha az, her Posix uyumlu kabukla çalışmayabilir. ve bazen posix uyumlu kabukları. Yani YMMV. Fakat bildiğim kadarıyla bash ile güvenilir bir şekilde çalışıyor.
Kanıt olarak, burada bash dd
olarak üzerine basıp eklemeye yarayan bash'deki 99 şişe bira programının "loop'suz" bir uygulaması var. Dosya, tam olarak aynı uzunluktaki bir yorumla; Son sonucun kendi kendini değiştiren davranış olmadan yürütülebilmesi için bunu yaptım.)
#!/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} #