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
, ksh
veya zsh
kabuk olarak kabul edilir.
sed
Yalnı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/
( re
keyfi 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 re
1 hattında veya sonraki satırda oluşur.
1,/re/
Bunu, ilk satırdan sonrakine re
ve 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 re
maçı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
sed
BSD (macOS) gibi yalnızca POSIX özelliklerised
( GNU ile de çalışır sed
):
Yana 0,/re/
kullanılamaz ve form 1,/re/
algılamaz re
o (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 -e
seçeneğe bölmek, gerçek bir yeni satır kullanmaya alternatiftir: -e
normalde bir satırsonunun gitmesi gereken her komut dizisini sonlandırın .
1 s/foo/bar/
foo
orada bulunursa, yalnızca 1. satırın yerine geçer . Öyleyse t
, komut dosyasının sonuna dallanır (satırda kalan komutları atlar). ( t
Bir 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 sed
sitesindeki 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ı 1
1. 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 ( 1
aralı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 .
//