Dosyanın sonuna henüz henüz gelmediyse bir satır nasıl eklenir?


10

Yalnızca komut dosyası kurşun geçirmez yapmak için henüz mevcut değilse bir dosyayı yerinde ekleyerek düzenlemek istiyorum.

Normalde şöyle bir şey yaparım:

cat >> ~/.bashrc <<EOF
export PATH=~/.composer/vendor/bin:\$PATH
EOF

Bunu ansible ( line+ insertafter=EOF+ regexp) ile yapmak da mümkündür , ancak bu başka bir hikaye.

Vi / ex gibi bir şey yapabilirdi:

ex +'$s@$@\rexport PATH=\~/.composer/vendor/bin:$PATH@' -cwq ~/.bashrc

ama sonra aynı hattı tekrarlamadan hattın zaten orada olup olmadığını (ve dolayısıyla hiçbir şey yapmadığını) nasıl kontrol edebilirim?

Ya da Ex düzenleyicide yapmanın daha kolay bir yolu var mı?


Dış kaynak kullanamıyor musunuz? grep -Fq 'export PATH=~/.composer/vendor/bin:$PATH' ~/.bashrc || ex ...(veya catbu konuda)?
muru

Bunun bu yaklaşıma benzer bir şey olabileceğine inanıyorum , ancak tam tersi (string orada olmadığında bir şey yap).
kenorb

ex ~/.bashrc -c "if search('export PATH=\~\/.composer\/vendor\/bin:\$PATH')>0 | norm quit | endif | norm Aexport PATH=~/.composer/vendor/bin:$PATH"
Alex Kroll

1
exportBir komut olduğuna dikkat edin , bu nedenle satırın geri kalanı bir ödev DEĞİL bir kabuk kelimesidir. Bu nedenle (kullanılmayan export) değişken bir atamadan farklı olarak , çift ​​tırnaklara ihtiyacınız vardır , yoksa boşlukta bozulur . Ayrıca bkz . PATH'ye doğru bir yol nasıl eklenir .
Wildcard

1
(Yukarıdaki bağlantılar da iyi olmasına rağmen) dün aradığım gerçek bağlantı buldum. Yerel değişken ataması için tırnak işaretleri gerekli mi?
Wildcard

Yanıtlar:


6

Kurşun geçirmez olmak istiyorsanız , muhtemelen yukarıdaki karmaşık seçeneklerden biraz daha taşınabilir bir şey istersiniz. POSIX özelliklerineex sadık kalacağım ve aptalca basit hale getireceğim: Eğer varsa (sadece kaç kez olursa olsun) satırı kaldırın, dosyanın sonuna ekleyin, ardından kaydedin ve çıkın:

ex -sc 'g/^export PATH=\~\/\.composer\/vendor\/bin:\$PATH$/d
$a
export PATH=~/.composer/vendor/bin:$PATH
.
x' ~/.bashrc

Daha fazla sağlamlık için normal ifadeyi sabitledim, ancak bu normal ifadeyle yanlışlıkla eşleşmenin neredeyse imkansız olduğunu düşünüyorum . (Bağlantılı, yani normal ifadeyi kullanmak anlamına gelir ^, $böylece normal ifade yalnızca tüm bir satırla eşleşirse eşleşir .)

+cmdSözdiziminin POSIX için gerekli olmadığını ve birden çok -cbağımsız değişkene izin vermenin ortak özelliği olmadığını unutmayın .


Bunu yapmanın başka birçok basit yolu vardır. Örneğin, satırı dosyanın sonuna ekleyin, ardından harici UNIX filtresi aracılığıyla dosyanın son iki satırını çalıştırın uniq:

ex -sc '$a
export PATH=~/.composer/vendor/bin:$PATH
.
$-,$!uniq
x' input

Bu çok çok temiz ve basittir ve ayrıca POSIX uyumludur. Bu kullanır Escape özelliğiex harici metin filtreleme için ve POSIX belirtilen kabuk yararuniq

Sonuçta, bir exedilir tasarlanmış yerinde dosya düzenleme için ve bugüne kadar bunu başarmak için en taşınabilir yoludur olmayan bir interaktif biçimde. viAslında orijinalden bile önce gelir - adı vi"görsel editör" içindir ve üzerine kurulduğu görsel olmayan editör buydu ex.)


Daha da fazla basitlik için (ve tek bir satıra azaltmak için), printfkomutları şu adrese göndermek için kullanın ex:

printf %s\\n '$a' 'export PATH=~/.composer/vendor/bin:$PATH' . '$-,$!uniq' x | ex input


2

Olası bir çözüm, bunu yapmak için bir işlev oluşturmaktır:

function! AddLine()

    let l:res = 0
    g/export PATH=\~\/.composer\/vendor\/bin:\\\$PATH/let l:res = l:res+1

    if (l:res == 0)
        normal G
        normal oexport PATH=~/.composer/vendor/bin:\$PATH
    endif

endfunction

İlk önce l:res, satırın oluşum sayısını saymak için kullanılacak bir yerel değişken yaratırız .

Biz kullanmak globalçizgi eşleştirilir her seferinde: komutunu l:resartırılır.

Son l:resolarak hala 0 ise, satırın dosyada görünmemesi anlamına gelir, bu nedenle sayesinde son satıra gideriz Gve oüzerine eklenecek satırı yazdığımız yeni bir satır oluştururuz .

1'e Not I değerini ayarlamak için kullanılan yöntemi l:resbiraz ağırdır ve @Alex önerdiği biriyle değiştirilebilir olabilir onun cevabını gibi bir şeyle:

let l:res = search('export PATH=\~\/.composer\/vendor\/bin:\\\$PATH')

Not 2 Ayrıca işlevi daha esnek hale getirmek için argümanları kullanabilirsiniz:

function! AddLine(line)

    let l:line =  escape(a:line, "/~$" )

    let l:res = 0
    exe "g/" . l:line . "/let l:res = l:res+1"

    if (l:res == 0)
        normal G
        exe "normal o" . a:line
    endif

endfunction
  • Aramada soruna neden olabilecek karakterlerin önüne escape()a ekleme hilesine dikkat edin \.
  • Ayrıca \işlevi çağırırken yine de kendiniz kaçmanız gerekeceğini unutmayın ( \Otomatik olarak kaçmayı başaramadım ):

    call AddLine("export PATH=~/.composer/vendor/bin:\\$PATH")
    

2

Deneyin:

ex ~/.bashrc -c "if search('export PATH=\~\/.composer\/vendor\/bin:\$PATH')>0 | norm quit | endif | norm Aexport PATH=~/.composer/vendor/bin:$PATH"

Ex modu ile -block :appendiçinde if endifçalışmaz unutmayın (bakınız VimDoc ) bu yüzden norm A...dışarı koymak zorunda .


1

Normalde kullanıyorum:

perl -i -p0e '$_.="export PATH=~/bin:\$PATH\n" unless m!~/bin:!' ~/.bashrc

1

Birçoğunun varlığını basitleştirmek ve önlemek için \, eklenecek çizgi olacaktır export PATH=mybin:PATH.

Ana strateji: "olmayan mybin" metni (tüm dosya) yerine text + mybin-path-definition yazın:

 vim  +'s#\v%^((.|\n)(mybin:)@!)*%$#&\rexport PATH=mybin:PATH#e' -cx bashrc

veya daha didaktik girinti ile :

s#                                    substitute
   \v                                  very magical to redude \

   %^                                  file begin
   ((.|\n)(mybin:)@!)*                 multi-line str without "mybin:"
                                         (any char not followed by "mybin")*
   %$                                  end of file
 #                                    by

Bir eşleşmemiz varsa:

  1. &tam metnini sahiptir bashrcve
  2. & içermiyor /mybin:/

yani:

 #                                    by ...
   &                                   all file
   export PATH=mybin:PATH              and the new path
 #e                                   don't complain if patt not found

-cx                                   save and leave 

GÜNCELLEME : Son olarak, bir vim betiği hazırlayabiliriz:

$ cat bashrcfix

#!/usr/bin/vim -s
:e ~/fakebashrc
:s#\v%^((.|\n)(mybin:)@!)*%$#&\rexport PATH=mybin:PATH#e
:x

chmod 755 ve yükleyin. Kullanımı:bashrcfix


dikkatli olun: \vmodda, =isteğe bağlı anlamına gelir


1

Bu cevapların çoğu, eski kabuk komutlarına ne dersiniz?

grep composer/vender ~/.bashrc || cat >> ~/.bashrc <<EOF
export PATH=~/.composer/vendor/bin:\$PATH
EOF

Bu kolayca bir Bash işlevi olabilir:

addBashrcPath() {
  if ! grep "$1" ~/.bashrc >/dev/null 2>&1; then
    printf 'export PATH=%s:$PATH' "$1" >> ~/.bashrc
  fi
}

addBashrcPath "~/.composer/vendor/bin"

EDIT : grep çıkış kodu önemlidir ve bu durumda kullanımı tersine çevrilmesi gerekir ! grep; grep -vbu durumda beklendiği gibi çıkmayacak. @Joeytwiddle bahşiş için teşekkürler.


Sana grep -vistediğin çıkış kodunu verdiğini sanmıyorum . Ama ! grepyapmalı.
joeytwiddle

Eğer durum buysa o zaman bile gerek yok -vsadece !.
Sukima

Kesinlikle. Bu düzeltmeyi yapmak için cevabınızı düzenleyebilirsiniz.
joeytwiddle

1
1. kullanmalıdır -Fböylece grepDosnt normal ifadeler olarak karakterleri yorumlamak ve 2. -qyerine kadar yönlendirme /dev/null. Soru hakkındaki önceki yorumuma bakın .
muru

Güzel nokta. Ne kadar taşınabilir -qve -Fseçenekler mi merak ediyorsunuz ? >/dev/nullFarklı platformlar arasında daha evrensel olduğunu düşündüm (sun vs hp vs Mac OS X vs Ubuntu vs FreeBSD vs…)
Sukima
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.