sed: bulunursa satırı değiştirir veya bulunmazsa dosyanın sonuna ekler mi?


34

Yalnızca yorumlar içeren (# ile başlayan) ve VARIABLE = değer satırlarını içeren tek bir girdi dosyasıyla, bulunursa tek bir değişken için bir değerin değiştirilmesi ve aksi takdirde bulunmazsa çifti dosyanın sonuna eklemek mümkün müdür?

Geçerli yöntemim, ilk geçişte silerek, ardından ikinci geçişte dosyanın sonuna ekleyerek çalışır, ancak bu yöntem satır sırasını bozar (ve ayrıca iki farklı komuttur):

sed -r "/^FOOBAR=.*$/d"      -i samefile &&
sed -r "$ a\FOOBAR=newvalue" -i samefile

Bunu yapmak için zaten var mı, yani. satır düzenini tek bir satırda tutmak? Başka bir yardımcı program (awk, ...) bunu yaparsa, baştan sona devredeceğim.

Yanıtlar:


29

Bu aslında oldukça basittir sed: bir satır eşleşirse heski alana skopyalarsanız değeri ubstitute yapın.
La Açık $sıralanmıyorlar e xikincisi boşsa değişim tutma alanı ve desen uzay sonra kontrol edin. Boş değilse, ikame işlemi zaten yapılacak hiçbir şey yapılmadığı anlamına gelir. Boşsa, bu eşleşme bulunmadığı anlamına gelir, bu nedenle desen boşluğunu istenen değişkenle = değerle değiştirin, ardından tutma arabelleğindeki geçerli satıra ekleyin. Sonunda, e xtekrar değişir:

sed '/^FOOBAR=/{h;s/=.*/=newvalue/};${x;/^$/{s//FOOBAR=newvalue/;H};x}' infile

Yukarıdaki gnu sedsözdizimidir. Taşınabilir:

sed '/^FOOBAR=/{
h
s/=.*/=newvalue/
}
${
x
/^$/{
s//FOOBAR=newvalue/
H
}
x
}' infile

1
newvalueBir değişkende saklanırsa bu nasıl görünür ?
user1810087

sed "/^${varName}=/{h;s/=.*/=${varValue}/};\${x;/^$/{s//${varName}=${varValue}/;H};x}" ${VARFILE}değişkenlerle, değişken ikamesine izin vermek için çift tırnak işareti ve ve $bu değerin saklı olması durumunda, bu noktada ikame olmayan bir değerden $$varNamesed "/^${varName}=/{h;s/=.*/=${!varName}/};\${x;/^$/{s//${varName}=${!varName}/;H};x}" ${VARFILE}
kaçmak

1
Bu çözüm 'basit' lol değil. Ama işe yarıyor. sed man sayfaları, gözden geçirilmesi en kolay şeyler değildir, ifadenin her bölümünün etkisini ayrıntılarıyla
anlatırsanız

18

Bu muhtemelen kısaltılabilir. Tek bir sed komutu değildir ve grep kullanır, ancak temelde istediğiniz şey bu gibi görünmektedir. Tek bir satırdır ve dosyayı yerinde düzenler (geçici dosyalar olmadan).

grep -q "^FOOBAR=" file && sed "s/^FOOBAR=.*/FOOBAR=newvalue/" -i file || 
    sed "$ a\FOOBAR=newvalue" -i file

13

Çalışmak kolay sedbulamadığım için daha basit bir yaklaşım sed hold space. hold spaceKonforunuz varsa , don_crissti yaklaşımını kullanmak, mevcut çizgiden bir şeyleri korumak için ek fırsat verir, ancak bu genellikle çok nadirdir.

Bu yaklaşımda, sadece bırakmak istediğiniz çizgiden başka bir şey yazmazsınız ve sonunda değiştirmeyi eklersiniz.

sed -n -e '/^FOOBAR=/!p' -e '$aFOOBAR=newvalue' infile

1
Varolan ancak eski olmayan bir değeri olan bir dosyayı güncellemeyi planlıyorsanız, bu sürüm çok iyidir.
guillem

3

Diğer cevaplara dayanarak, eğer yapmak istediğiniz şey bir değişkenin değerini değiştiriyorsa, bu değişken dosyada mevcutsa ve eğer değilse (dosyanın gönderdiği sedkomutların yaptığı değil) dosyanın sonuna ekleyin. bunu deneyebilirim:

perl -ne '$c=1 if s/^FOOBAR=.*$/FOOBAR=newvalue/;  
             print; 
             END{print "FOBAR=newvalue" unless $c==1}' file > tmpfile && 
mv tmpfile file

1

"Yerinde düzenleme" otomatik olmasa da, awk için biraz daha kolay:

awk -v varname="FOOBAR" -v newval="newvalue" '
    BEGIN {FS = OFS = "="}
    $1 == varname {$2 = newval; found = 1}
    {print}
    END {if (! found) {print varname, newval}}
' file > tempfile &&
mv tempfile file

1

Boş bir kayıt oluşturmak için grepve echodüğmelerini kullanın :

grep -q '^FOOBAR=' somefile || echo 'FOOBAR=VALUE' >> somefile
sed -i 's/FOOBAR=.*$/FOOBAR=VALUE/' somefile 

Her satır sıfır hata koduyla kaçar.


Ekstra bir komut eklerken satır sıralamasını kaybedersiniz grepveecho
BlakBat

Gerçekten de, yeni öğeleri dosyanın sonuna eklerseniz, ancak eski bir değeri değiştirirseniz sipariş vermeye devam edin.
MUY Belçika

0

Aslında aşağıdakiler ile çalışır: sed -i '/^FOOBAR=/{h;s/=.*/=newvalue/};${x;/^$/{s//FOOBAR=newvalue/;H};x}' infile Seçilen cevapta -i eksik.


3
Bu gerçekten bir yorum ve asıl sorunun cevabı değil . Bir yazarın açıklamasını eleştirmek veya talep etmek için, yazdıklarının altında bir yorum bırakın; istediğiniz zaman kendi yazılarınıza yorum yapabilirsiniz ve yeterli saygınlık elde ettiğinizde , herhangi bir yayına yorum yazabilirsiniz . Lütfen okuyun Neden yorum yapmak için 50 itibara ihtiyacım var? Bunun yerine ne yapabilirim?
DavidPostill

-1

perl ve yerinde bunu yapmak benim için iyi çalışıyor:

grep ^FOOBAR= my.file && perl -i -ple "s/^FOOBAR=.+/FOOBAR=newvalue/g" my.file || echo FOOBAR=newvalue >> my.file

2
Bu cevap birçok yönden kötü ! grepve echove perlbunun yerine her şeyi yapmanın perl? Ayrıca, bir dosyaya ( >> my.file) okurken onu yazmak ( grep my.file)?
vladr
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.