Bir bakış , birçok yararlı ait mevcut cevapları ile tamamlanmaktadır açıklamalar :
Buradaki örneklerde basitleştirilmiş bir kullanım örneği kullanılmıştır: 'foo' kelimesini yalnızca ilk eşleşen satırdaki 'bar' ile değiştirin.
Kullanılması sayesinde ISO C tırnakla ( $'...') örnek giriş hatlarını sağlamak için bash, kshveya zshkabuk olarak kabul edilir.
sedYalnızca GNU :
Ben Hoffstein en anwswer GNU bir sağladığını gösterir bize uzantısı için için POSIX şartnamesed o aşağıdaki verir 2-adres formu : 0,/re/( rekeyfi bir normal ifade burada gösterir).
0,/re/normal ifadenin ilk satırda da eşleşmesini sağlar . Başka bir deyişle: Böyle bir adres maçları o limitini içeren bir karşı 1 hat yukarıya aralığını ve yaratacak re- ister re1 hattında veya sonraki satırda oluşur.
1,/re/Bunu, ilk satırdan sonrakine reve sonraki satırlarda eşleşen çizgiye kadar uzanan bir aralık oluşturan POSIX uyumlu formla karşılaştırın ; diğer bir deyişle: 1. satırda meydana gelirse bir remaçın ilk tekrarını tespit etmez ve ayrıca en son kullanılan normal ifadenin yeniden kullanımı için steno kullanımını önler// (bir sonraki noktaya bakın). 1
Bir 0,/re/adresi s/.../.../, aynı normal ifadeyi kullanan bir (yerine koyma) çağrısıyla birleştirirseniz , komutunuz değiştirmeyi yalnızca eşleşen ilk satırda etkili bir şekilde gerçekleştirir re. en son uygulanan normal ifadeyi yeniden kullanmak için
sed kullanışlı bir kısayol sağlar : boş bir sınırlayıcı çifti// ,.
$ sed '0,/foo/ s//bar/' <<<$'1st foo\nUnrelated\n2nd foo\n3rd foo'
1st bar # only 1st match of 'foo' replaced
Unrelated
2nd foo
3rd foo
sedBSD (macOS) gibi yalnızca POSIX özelliklerised ( GNU ile de çalışır sed):
Yana 0,/re/kullanılamaz ve form 1,/re/algılamaz reo (yukarıya bakınız) ilk satırında ortaya olursa, 1 hat için özel işlem gereklidir .
MikhailVS'nin cevabı , burada somut bir örnek haline getirilen teknikten bahsediyor:
$ sed -e '1 s/foo/bar/; t' -e '1,// s//bar/' <<<$'1st foo\nUnrelated\n2nd foo\n3rd foo'
1st bar # only 1st match of 'foo' replaced
Unrelated
2nd foo
3rd foo
Not:
Boş normal ifade //kısayolu burada iki kez kullanılır: bir kez aralığın bitiş noktası için ve bir kez sçağrıda; her iki durumda da, normal ifade fooörtük olarak yeniden kullanılır, bu da onu kopyalamamıza izin verir, bu da hem daha kısa hem de daha sürdürülebilir bir kod sağlar.
POSIX sed, burada olduğu gibi, bir etiketin adından veya hatta çıkarılmasından sonra gibi belirli işlevlerden sonra gerçek satırsonlarına ihtiyaç duyar t; betiği stratejik olarak birden çok -eseçeneğe bölmek, gerçek bir yeni satır kullanmaya alternatiftir: -enormalde bir satırsonunun gitmesi gereken her komut dizisini sonlandırın .
1 s/foo/bar/fooorada bulunursa, yalnızca 1. satırın yerine geçer . Öyleyse t, komut dosyasının sonuna dallanır (satırda kalan komutları atlar). ( tBir etikete yalnızca en son sçağrı gerçek bir ikame gerçekleştirdiyse dallanır; bir etiket yokluğunda, burada olduğu gibi, komut dosyasının sonu dallanır).
Bu olduğu zaman, aralık adresi 1,//genellikle ilk geçtiği bulur, hat 2'den başlayan , edecek olup neticesinde, ve aralık olacak değil mevcut hat zaten, adres değerlendirilir çünkü işlenecek 2.
1 satırda eşleşen bir Tersine, 1,// olacak girilecek ve gerçek ilk maçı bulacaksınız.
Net etki, GNU ile aynıdır sedsitesindeki 0,/re/1st hattı ya da başka bir oluşup oluşmadığını değiştirilir, sadece ilk seferinde.
Aralık dışı yaklaşımlar
Potong cevabı gösteren döngü teknikleri bir dizi ihtiyacını bypass ; GNU sed sözdizimini kullandığı için POSIX uyumlu eşdeğerleri aşağıda verilmiştir :
Döngü tekniği 1: İlk eşleşmede ikame işlemini gerçekleştirin, ardından kalan çizgileri olduğu gibi yazdıran bir döngü girin :
$ sed -e '/foo/ {s//bar/; ' -e ':a' -e '$!{n;ba' -e '};}' <<<$'1st foo\nUnrelated\n2nd foo\n3rd foo'
1st bar
Unrelated
2nd foo
3rd foo
Döngü tekniği 2, yalnızca ufacık dosyalar için : tüm girişi belleğe okuyun, sonra tek bir değişiklik yapın .
$ sed -e ':a' -e '$!{N;ba' -e '}; s/foo/bar/' <<<$'1st foo\nUnrelated\n2nd foo\n3rd foo'
1st bar
Unrelated
2nd foo
3rd foo
1 1.61803 , 1,/re/müteakip olan ve olmayan şeylerin örneklerini sunar s//:
- sed '1,/foo/ s/foo/bar/' <<<$'1foo\n2foo'verimler $'1bar\n2bar'; yani, her iki satır da güncellendi, çünkü satır numarası 11. satırla eşleşir ve regex /foo/- aralığın sonu - yalnızca sonraki satırdan başlayarak aranır. Bu nedenle, bu durumda her iki satır seçilir ve s/foo/bar/ikame her ikisinde de gerçekleştirilir.
- sed '1,/foo/ s//bar/' <<<$'1foo\n2foo\n3foo' başarısız : sed: first RE may not be empty(BSD / macOS) ve sed: -e expression #1, char 0: no previous regular expression(GNU) ile, çünkü 1. satır işlenirken ( 1aralıktan başlayan satır numarası nedeniyle ), henüz normal ifade uygulanmadığından,//hiçbir şey ifade etmiyor.
GNU'nun sedözel 0,/re/sözdizimi dışında, bir satır numarasıyla başlayan herhangi bir aralık etkili bir şekilde kullanılmasını engeller .
//