Dosyaya yalnızca henüz mevcut değilse satır ekleme


157

Bir yapılandırma dosyasının sonuna aşağıdaki satırı eklemeniz gerekir:

include "/configs/projectname.conf"

adlı bir dosyaya lighttpd.conf

Bunu sedyapmak için kullanmayı düşünüyorum ama nasıl yapılacağını anlayamıyorum.

Bunu yalnızca çizgi zaten yoksa ekleyebilir miyim?


Bir ini dosyasını düzenlemeye çalışıyorsanız, araç crudiniiyi bir seçenek olabilir (ancak henüz lighthttpd için değil)
rubo77

Yanıtlar:


292

Sadece basit tut :)

grep + echo yeterli olmalıdır:

grep -qxF 'include "/configs/projectname.conf"' foo.bar || echo 'include "/configs/projectname.conf"' >> foo.bar

Düzenleme: @cerin ve @ thijs-wouters önerileri dahil .


2
Çıkışı bastırmak için grep'e -q anahtarını eklerdim: grep -vq ...
Dave Kirby

1
FYI, -v ve && kullanarak hile yapmak istemiyor, oysa || -v olmadan çalışır.
bPizzi

3
Bu sadece çok basit çizgiler için geçerlidir. Aksi takdirde, grep satırınızdaki alfa olmayan karakterlerin çoğunu kalıplar olarak yorumlar ve dosyadaki satırı algılamamasına neden olur.
Cerin

2
Güzel bir çözüm. Bu aynı zamanda daha karmaşık ifadeleri tetiklemek için de işe yarar. Benimki bir yapılandırma dosyasına çok satırlı bir yorumlu metin echotetiklemek için kullanır cat.
Eric L.

2
-sDosya mevcut olmadığında hataları yok saymak için ekleyin ve yalnızca bu satırla yeni bir dosya oluşturun.
Frank

78

Bu kullanarak, temiz okunabilir ve yeniden kullanılabilir bir çözüm olacağını grepve echozaten var olmayan, yalnızca bir dosyaya bir satır eklemek için:

LINE='include "/configs/projectname.conf"'
FILE='lighttpd.conf'
grep -qF -- "$LINE" "$FILE" || echo "$LINE" >> "$FILE"

Tüm çizgi kullanımını eşleştirmeniz gerekiyorsa grep -xqF

-sDosya mevcut olmadığında hataları yok saymak için ekleyin ve yalnızca bu satırla yeni bir dosya oluşturun.


5
Kök izinlerine ihtiyacınız olan bir dosyaya:sudo grep -qF "$LINE" "$FILE" || echo "$LINE" | sudo tee -a "$FILE"
nebffa

Bu, çizgi a ile başladığında çalışmaz -.
hyperknot

@zsero: iyi nokta! Ben --grep komutunda ekledim , bu yüzden artık bir çizgi ile başlayan bir $ LINE'ı seçenek olarak yorumlamayacak.
rubo77

13

İşte bir sedsürüm:

sed -e '\|include "/configs/projectname.conf"|h; ${x;s/incl//;{g;t};a\' -e 'include "/configs/projectname.conf"' -e '}' file

Dizeniz bir değişkendeyse:

string='include "/configs/projectname.conf"'
sed -e "\|$string|h; \${x;s|$string||;{g;t};a\\" -e "$string" -e "}" file

Kısmi bir dizeyi tam / güncellenmiş yapılandırma dosyası girişiyle değiştiren veya satırı gerektiği gibi sed -i -e '\|session.*pam_mkhomedir.so|h; ${x;s/mkhomedir//;{g;tF};a\' -e 'session\trequired\tpam_mkhomedir.so umask=0022' -e '};:F;s/.*mkhomedir.*/session\trequired\tpam_mkhomedir.so umask=0022/g;' /etc/pam.d/common-session
ekleyen bir komut

Güzel, bana çok yardımcı oldu +1. sed ifadenizi açıklar mısınız?
Rahul

Bu çözümün açıklamalı bir açıklamasını görmek isterim. sedYıllarca kullandım ama çoğunlukla sadece skomut. holdVe patternuzay takasları beni dışındadır.
normalde

11

Korumalı bir dosyaya yazıyorsanız, biri sudo olamaz çünkü @drAlberT ve @ rubo77 'ın yanıtları sizin için çalışmayabilir >>. Bir benzer şekilde basit bir çözüm , daha sonra, kullanmak olacaktır tee --append(MacOS veya tee -a):

LINE='include "/configs/projectname.conf"'
FILE=lighttpd.conf
grep -qF "$LINE" "$FILE"  || echo "$LINE" | sudo tee --append "$FILE"

6

Bir gün, bir başkası, Eğer var "eski kod" olarak bu kodla uğraşmak aşağıdakiler gibi, bir az zahiri kod yazmak, o zaman kişinin minnettar olacağını

grep -q -F 'include "/configs/projectname.conf"' lighttpd.conf
if [ $? -ne 0 ]; then
  echo 'include "/configs/projectname.conf"' >> lighttpd.conf
fi

1
Maalesef, kabuk bilmiyorsanız, gidin ve Windows'u yönetin. && ve || kullanan çözümler normal kabuk sözdizimidir ve herhangi bir yetkili yönetici tarafından anlaşılmalıdır. Orada ezoterik bir şey yok.
Graham Nicholls

3
Yorumunuz için teşekkürler Graham! Evet, normal kabuk sözdizimi. Ve evet, herhangi bir yetkili yönetici bunu anlamalıdır. Bununla birlikte, kabuk içindeki ifade değerlendirme algoritmasının bir yan etkisine dayalı olarak çalışır. Bu yüzden, orijinal noktam olan basit hariç, istediğiniz gibi arayabilirsiniz.
Marcelo Ventura


6

başka bir sed çözümü her zaman son satıra eklemek ve önceden var olanı silmek.

sed -e '$a\' -e '<your-entry>' -e "/<your-entry-properly-escaped>/d"

"düzgün bir şekilde kaçan", girişinizle eşleşen bir normal ifade koymak, yani gerçek girişinizden tüm normal ifade kontrollerinden kaçmak, yani ^ $ / *? + () önüne ters eğik çizgi koymak anlamına gelir.

Bu, dosyanızın son satırında başarısız olabilir veya sarkan yeni satır yoksa, emin değilim, ancak bu bazı şık dallanma ile ele alınabilir ...


1
Güzel bir astar, kısa ve okunması kolay. Etc / hosts güncellenmesi için büyük çalışır:sed -i.bak -e '$a\' -e "$NEW_IP\t\t$HOST.domain\t$HOST" -e "/.*$HOST/d" /etc/hosts
Noam Manos

Daha küçük bir versiyon:sed -i -e '/<entry>/d; $a <entry>'
Jérôme Pouiller

@Jezz Girdi zaten dosyanın sonunda ise, bu başarısız olacağını düşünüyorum, çünkü dkomut sed programını yeniden başlatacak ve böylece asilme son satırda gerçekleşmişse, atlamayı atlayacaktır .
Robin479

Robin479 Damned @, append önce gerçekleştirilmek zorundadır delete: sed -i -e '$a<entry>' -e '/<entry>/d'. Neredeyse orijinal cevabınızla aynı.
Jérôme Pouiller

3

awk kullan

awk 'FNR==NR && /configs.*projectname\.conf/{f=1;next}f==0;END{ if(!f) { print "your line"}} ' file file

'Dosya dosyası' mı yoksa sadece 'dosya' mı?
webdevguy

Bu var file fileaynı dosyanın üzerine iki geçiş yapar çünkü. NR==FNRilk geçişte doğrudur, ancak ikinci geçişte doğru değildir. Bu yaygın bir Awk deyimidir.
üçlü

1

Grep kullanan cevaplar yanlış. Tüm satırı eşleştirmek için bir -x seçeneği eklemeniz gerekir, aksi takdirde #text to addtam olarak eklemek istediğinizde gibi satırlar eşleşir text to add.

Yani doğru çözüm şuna benzer:

grep -qxF 'include "/configs/projectname.conf"' foo.bar || echo 'include "/configs/projectname.conf"' >> foo.bar

1

Sed kullanarak: Satırın sonuna eklenir. Elbette her zamanki gibi değişkenleri de iletebilirsiniz.

grep -qxF "port=9033" $light.conf
if [ $? -ne 0 ]; then
  sed -i "$ a port=9033" $light.conf
else
    echo "port=9033 already added"
fi

Oneliner sed kullanma

grep -qxF "port=9033" $lightconf || sed -i "$ a port=9033" $lightconf

Yankı kullanmak kök altında çalışmayabilir, ancak böyle çalışacaktır. Ancak, parola isteyebileceğinden, bunu yapmak istiyorsanız, işleri otomatikleştirmenize izin vermez.

Belirli bir kullanıcı için kökten düzenlemeye çalışırken bir sorun yaşadım. Öncekini eklemek $usernamebenim için bir düzeltmeydi.

grep -qxF "port=9033" light.conf
if [ $? -ne 0 ]; then
  sudo -u $user_name echo "port=9033" >> light.conf
else
    echo "already there"    
fi

Stackoverflow'a hoş geldiniz! Lütfen bir cevap göndermeden önce soruyu dikkatle okuyun - OP sed kullanarak nasıl ekleneceğini sordu
Markoorn

-1

Bu yüzden kısıtlı yazma izinleri olan bir dosyayı düzenlemek gerekiyordu sudo. ghostdog74'ün cevabından çalışarak ve geçici bir dosya kullanarak:

awk 'FNR==NR && /configs.*projectname\.conf/{f=1;next}f==0;END{ if(!f) { print "your line"}} ' file > /tmp/file
sudo mv /tmp/file file

Bu doğru görünmüyor, yapılandırma satırı eksik olduğunda dosyadaki diğer satırları kaybedecek.
üçlü
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.