Dosyada bul ve değiştir ve dosyanın üzerine yaz çalışmıyor, dosyayı boşaltıyor


604

Komut satırı üzerinden bir HTML dosyasında bul ve değiştir komutunu çalıştırmak istiyorum.

Komutum şöyle görünüyor:

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html > index.html

Bunu çalıştırıp daha sonra dosyaya baktığımda boş. Dosyamın içeriğini sildi.

Dosyayı geri yükledikten sonra bu çalıştırdığınızda:

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html

stdoutDosyanın içeriği ve bulmak ve yürütülmesinden değiştirin.

Bu neden oluyor?


13
Perl alternatifi:perl -pi -w -e 's/STRING_TO_REPLACE/REPLACE_WITH/g;' index.html
Gjorgji Tashkovski

sedbir dize bulmak ve tüm satırı değiştirmek için çok ilgili komut: stackoverflow.com/questions/11245144/…
cregox

Yanıtlar:


917

Ne zaman kabuk görür > index.htmlkomut satırında bu dosyayı açar index.htmliçin yazılı tüm önceki içeriği üflemek.

Bunu düzeltmek için değişiklikleri yerinde yapma ve değişiklikleri yerinde yapmadan önce orijinal dosyanın bir yedeğini oluşturma -iseçeneğini geçmeniz gerekir sed:

sed -i.bak s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html

.Bak olmadan komut, Mac OSX gibi bazı platformlarda başarısız olur.


20
Söyleyen truncates the fileyerine opens the filemuhtemelen daha net hale getirir.
Mikel

12
En azından mac bilgisayarımda, ilk öneri işe yaramıyor ... bir dosyada yerinde değiştirme yapıyorsanız, bir uzantı belirtmelisiniz. En azından sıfır uzunluklu bir uzantıyı iletebilirsiniz: sed -i '' s / STRING_TO_REPLACE / STRING_TO_REPLACE_IT / g index.html
Tom Lianza

5
sed -i.bak 's /' $ arama '/' $ yerine '/ g' index.html
Fatima Zohra

33
osx üzerinde, -i parametresi olarak boş bir dize kullanın '' gibi:sed -i '' 's/blah/xx/g'
Pierre Houston

4
ama seninki ne .baksonra sed -i?
Patrizio Bertoni

210

Alternatif, kullanışlı bir model:

sed -e 'script script' index.html > index.html.tmp && mv index.html.tmp index.html

Bu, -iseçeneği kullanmadan hemen hemen aynı etkiye sahiptir ve ek olarak, sed komut dosyası bir nedenle başarısız olursa, giriş dosyasının tıkanmadığı anlamına gelir. Ayrıca, düzenleme başarılı olursa, etrafta kalan yedek dosya kalmaz. Bu tür deyim Makefiles'de yararlı olabilir.

Oldukça fazla seds -iseçeneği var, ama hepsi değil; posix sed olmayan biridir. Bu nedenle, taşınabilirliği hedefliyorsanız, en iyisi kaçınılmalıdır.


9
Düzenleme başarısız olursa yedekleme dosyası etrafında döşeme ve giriş dosyası clobbering için +1. Mac üzerinde kusursuz çalıştı.
Mike Grace

Benim için mükemmel çalıştı. Teşekkür ederim! (Mac'te)
ilgilenen

1
Bu benim için mükemmel çalıştı Ubuntu Server 14.04 sed -i dosya sıfırlama tuttu nerede.
Chris Giddings

2
Son derece küçük geliştirme:... && mv index.html{.tmp,}
EdwardGarson

5
@EdwardGarson Gerçekten, ben yazsaydım muhtemelen kullanacağım şey budur - katılıyorum katılıyorum - ama sh(doğru hatırlıyorsam) bu {...}genişlemeye sahip değil . Bir Makefile'de bunun shyerine kullanıyor olabilirsiniz bash, bu nedenle taşınabilirliği (veya posixliği) hedefliyorsanız, bu yapıdan kaçınmanız gerekir.
Norman Gray

95
sed -i 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' index.html

Bu, index.html dosyasında genel bir yerinde değişiklik yapar. Dizeyi tırnak içine almak sorgu ve boşluk boşluk ile ilgili sorunları önler.


57

sed's -i seçeneğini kullanın, örn.

sed -i bak -e s/STRING_TO_REPLACE/REPLACE_WITH/g index.html

Ne anlama geliyor? sed: -i stdin ile kullanılamaz
sheetal

2
Beyaz boşluk içeriyorsa deseninizi tırnak içine almayı unutmayın -'s/STRING_TO_REPLACE/REPLACE_WITH/g'
Doug Thompson

@sheetal: dosyaların-i yerinde düzenlenmesini sağlar , bu nedenle dosyayı stdin girdisiyle birleştirmek mantıklı değildir .
mklement0

Bu macOS'ta işe yarayabilir, ancak Arch Linux'ta benim için çalışmıyor.
xdevs23

-E olmadan, kabul edilen cevap MacOS, Catalina üzerinde çalışmaz. -E ile işe yarıyor.
cwhiii

18

Birden çok dosyayı değiştirmek (ve her birinin yedeğini * .bak olarak kaydetmek) için:

perl -p -i -e "s/\|/x/g" *  

dizinindeki tüm dosyaları alıp yerini alacak |olan x bir “Perl pasta” olarak adlandırılan bu (kolay bir pasta gibi)


1
Sorun etiketlerine bakmak isteyen birini görmek güzel, sadece etiketleri değil. OP sedbir gereklilik olarak belirtmedi , sadece denenmiş araç olarak kullandı.
user7412956

14

-iYerinde düzenleme seçeneğini kullanmayı denemelisiniz .


6
sed -i.bak "s#https.*\.com#$pub_url#g" MyHTMLFile.html

Eklenecek bir bağlantınız varsa, bunu deneyin. URL'yi yukarıdaki gibi arayın (https ile başlayıp burada.com ile biterek) ve bir URL dizesiyle değiştirin. $pub_urlBurada bir değişken kullandım . sburada arama ve gküresel değiştirme anlamına gelir.

İşe yarıyor !


6

Uyarı: Bu tehlikeli bir yöntemdir! Linux'ta i / o arabelleklerini kötüye kullanır ve belirli arabellekleme seçenekleriyle küçük dosyalar üzerinde çalışmayı başarır. Bu ilginç bir merak. Ama gerçek bir durum için kullanmayın!

Ayrıca -iseçeneği sed size kullanabilirsiniz teeyarar .

Gönderen man:

tee - standart girişten okuma ve standart çıkış ve dosyalara yazma

Yani, çözüm şöyle olurdu:

sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee | tee index.html

- burada teeboru hattının arabelleğe alındığından emin olmak için tekrarlanır. Daha sonra, boru hattındaki tüm komutlar üzerinde çalışmak için bir girdi elde edilene kadar engellenir. Boru hattındaki her komut, yukarı akış komutları , komutun girişine 1 tampon bayt (boyut bir yerde tanımlanır ) yazdığında başlar . Son komuttee index.html dosyayı yazmak için açan ve dolayısıyla boşaltan , yukarı akış boru hattı bittikten ve çıktı boru hattı içindeki arabellekte bulunduktan sonra çalışır.

Büyük olasılıkla aşağıdakiler işe yaramaz:

sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee index.html

- boru hattının her iki komutunu da engellemeden aynı anda çalıştıracaktır. (Boru hattını bloke olmadan tampon ile yerine tampon hattı ile bayt satır geçmelidir. Çalıştırdığınızda aynı cat | sed s/bar/GGG/. Daha etkileşimli ve sadece 2 komutların genellikle boru hatları tamponlama ve engelleme olmadan çalıştırmak engelleme olmadan. Daha uzun boru hatları tamponlanır.) tee index.htmlİrade dosyayı yazmak için açın ve boşaltılacaktır. Ancak, arabelleği her zaman açarsanız, ikinci sürüm de çalışır.


3
Tee çıktı dosyası da hemen açılır ve tüm komut için boş bir index.html oluşturur.
sjngm

3
Bu olacak bozuk daha büyük olan herhangi bir girdi dosya boru hattı tampon (tipik olarak 64 KB olan) . (@sjngm: dosyada olduğu gibi anında kesilmez >, ancak önemli olan bunun veri kaybına neden olabilecek kırık bir çözüm olduğu anlamına gelir).
mklement0

4

Komutla ilgili sorun

sed 'code' file > file

yani fileaslında sed işlemek bulmadan kabuk tarafından kesilir. Sonuç olarak, boş bir dosya alırsınız.

Bunu yapmanın en iyi yolu -i, diğer yanıtların önerdiği gibi yerinde düzenlemek için kullanmaktır . Ancak, bu her zaman istediğiniz şey değildir. -iorijinal dosyayı değiştirmek için kullanılacak geçici bir dosya oluşturur. Orijinal dosyanız bir bağlantıysa bu sorunludur (bağlantı normal bir dosya ile değiştirilecektir). Bağlantıları korumanız gerekiyorsa, sed'in çıktısını dosyaya yazmadan önce saklamak için geçici bir değişken kullanabilirsiniz, örneğin:

tmp=$(sed 'code' file); echo -n "$tmp" > file

Daha da iyisi, kullanım printfyerine echoberi echosürecine muhtemeldir \\olarak \bazı kabukları (örneğin çizgi) içinde:

tmp=$(sed 'code' file); printf "%s" "$tmp" > file

1
Bağlantıları korumak için +1. Ayrıca geçici bir dosya ile çalışır:sed 'code' file > file.tmp; cat file.tmp > file; rm file.tmp
dashohoxha

3

Ve edcevap:

printf "%s\n" '1,$s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' w q | ed index.html

Codaddict'in yanıtını yinelemek için , kabuk önce "input.html" dosyasını silerek yeniden yönlendirmeyi işler ve sonra kabuk şimdi boş bir dosya geçirerek "sed" komutunu çağırır.


2
hızlı soru, neden insanlar cevapların ed"sürümünü" vermeye devam ediyor sed? daha hızlı çalışıyor mu?
cregox

6
Bazıları yerinde düzenleme sedyapmak için uygulanmaz -i. edher yerde bulunur ve düzenlemelerinizi orijinal dosyaya kaydetmenize izin verir. Ayrıca kitinizde birçok araç bulunması her zaman iyidir.
glenn jackman

tamam iyi. performans akıllıca, sanırım aynı. Teşekkürler!
cregox

2

Vim'i Ex modunda kullanabilirsiniz:

ex -sc '%s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g|x' index.html
  1. % tüm satırları seç

  2. x kaydet ve kapat


0

Çizgi aralığını tanımlayabileceğim ve cevabı bulabileceğim bir seçenek arıyordum. Örneğin, host1'i host2 yerine 36-57 satırından değiştirmek istiyorum.

sed '36,57 s/host1/host2/g' myfile.txt > myfile1.txt

Karakter durumunu yok saymak için gi seçeneğini de kullanabilirsiniz.

sed '30,40 s/version/story/gi' myfile.txt > myfile1.txt

0

Yukarıdaki doğru cevaplara gereken tüm saygıyla, bu tür komut dosyalarının "kuru çalıştırılması" her zaman iyi bir fikirdir, böylece dosyanızı bozmaz ve sıfırdan yeniden başlamak zorunda kalırsınız.

Komut dosyanızı çıktıyı dosyaya yazmak yerine komut satırına dökmesini sağlayın, örneğin:

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html

VEYA

less index.html | sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g 

Bu şekilde, dosyanızı kesmeden komutun çıktısını görebilir ve kontrol edebilirsiniz.

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.