Sed ile eğik çizgi içeren dizeler nasıl eklenir?


152

Yerel olarak geliştirilmiş bir Visual Studio projem var. Kod dosyalarının uzak bir sunucuya dağıtılması gerekir. Tek sorun, içerdikleri ve sabit kodlanmış URL'lerdir.

Proje gibi URL'ler içerir ?page=one. Bağlantının sunucuda geçerli olması için olması gerekir /page/one.

Dağıtımdan önce kod dosyalarımdaki tüm URL'leri sed ile değiştirmeye karar verdim, ancak eğik çizgilere takılı kaldım.

Bunun pek hoş bir çözüm olmadığını biliyorum, ancak basit ve bana çok zaman kazandıracak. Değiştirmem gereken toplam dizi sayısı 10'dan az. Kontrol edilmesi gereken toplam dosya sayısı ~ 30'dur.

Durumumu açıklayan örnek aşağıdadır:

Kullandığım komut:

sed -f replace.txt < a.txt > b.txt

replace.txt tüm dizeleri içeren:

s/?page=one&/pageone/g
s/?page=two&/pagetwo/g
s/?page=three&/pagethree/g

a.txt:

?page=one&
?page=two&
?page=three&

b.txtSed komutumu çalıştırdıktan sonraki içerik :

pageone
pagetwo
pagethree

İçermek istediğim b.txtşey:

/page/one
/page/two
/page/three


Yanıtlar:


286

En kolay yol, arama / değiştirme satırlarınızda farklı bir sınırlayıcı kullanmaktır, örneğin:

s:?page=one&:pageone:g

Her iki dizenin parçası olmayan herhangi bir karakteri sınırlayıcı olarak kullanabilirsiniz. Veya ters eğik çizgiyle ondan kaçabilirsiniz:

s/\//foo/

Hangisi /ile değiştirilir foo. Değiştirilen dizelerde hangi karakterlerin olabileceğini bilmediğiniz durumlarda (örneğin, kabuk değişkenleriyse) kaçan ters eğik çizgiyi kullanmak isteyebilirsiniz.


1
> Veya ters eğik çizgiyle kaçabilirsiniz. Farklı bir şey seçebilmek için bir dizede hangi karakterlerin olduğunu her zaman bilmediğiniz için, bunun bir örneği daha yararlı olacaktır. örneğin, bu: echo / | sed s / \ // a / g çalışmıyor: sed: -e ifade # 1, char 5: "s 'için bilinmeyen seçenek
Max Waterman

1
Bir tane daha ekleyebilir misin? Teşekkürler :) Çevreleyen çift tırnak işareti işe yarıyor gibi görünüyor: echo / | sed "s / \ // a / g"
Max Waterman

@MaxWaterman sed, regex komutunun çift tırnağa konulmasıyla ilgili standart çalışma prosedürüdür . Bunları cevabımda kullanmadım çünkü tüm sedkomut satırını göstermiyordum, sadece sedOP'nin yaptığı gibi sadece regex komut dizesini gösterdim. OP'nin yaptığı gibi bir dosyaya koyarsanız, alıntılara ihtiyacınız olmaz.
lurker

Evet, yeterince adil (belki de bahsedilebilir). Bu örnek yardımcı olur. Bazen çok fazla ters eğik çizgi koymam gerektiğini anlıyorum ... ve bu gerçekten kafa karıştırıcı oluyor. örneğin -e "s / '/ \\\\\\\\ & / g" Metnin yanlış olduğunu düşünüyorum, ancak: "Hangisi \ foo ile değiştirilir" - "Hangisi / foo ile değiştirilir" olmalıdır, hayır?
Max Waterman

@MaxWaterman bunu \ vs. / üzerinde yakaladığınız için teşekkürler. Onu düzeltti. sedBir kabuk betiğinde bir komutunuz varsa , daha fazla ters eğik çizgi gerekli olabilir (her ters eğik çizginin yeniden ters eğik çizgiyle işaretlenmesi gerekir).
lurker

107

sKomut ayırıcı olarak herhangi bir karakter kullanabilirsiniz; skullanıldıktan sonra hangi karakter gelirse gelsin . A kullanmak için büyüdüm #. Şöyle:

s#?page=one&#/page/one#g

5
OS X üzerinde BSD sed için man sayfası s komutundan bahseder: Yerine koyma dizesini desen uzayındaki normal ifadenin ilk örneği ile değiştirin. Ters eğik çizgi veya yeni satır dışında herhangi bir karakter, RE'yi ve değiştirmeyi sınırlandırmak için eğik çizgi yerine kullanılabilir. GNU sed için man sayfasının benzer bir şey söylediğine bahse girerim.
Tom Anderson

Mevcut kabul edilen cevap temelde bununla aynı ve bir dakika önce yayınlandı!
Tom Anderson

64

Sed hakkında çok yararlı ancak daha az bilinen bir gerçek, tanıdık s/foo/bar/komutun yalnızca eğik çizgileri değil, herhangi bir noktalama işaretini kullanabileceğidir. Yaygın bir alternatif, s@foo@bar@probleminizi nasıl çözeceğinizin açık hale gelmesidir.


İleriye doğru eğik çizgilerin yerine geçmek istediğinizde dahi tavsiyesi. Teşekkürler!
mbb

9

özel karakterlerden önce \ ekleyin:

s/\?page=one&/page\/one\//g

vb.


4
Bir şeyi gözden kaçırmış olabilirim, ama bunu denedim ve işe yaramadı. Denenmesi gereken bariz bir şey gibi görünüyordu, ama haklı olduğumu ve gerçekten işe yaramadığını varsayarsak, neden gönderelim?
codenoob

4
@codenoob (ve buraya gelen herkes) - baştaki 's' gereklidir. s/foo\/bar/foo_bar/çalışacak ama çalışmayacak /foo\/bar/foo_bar/.
MynockSpit

5

Geliştirdiğim bir sistemde sed ile değiştirilecek dizge, bir değişkende depolanan ve sed'e geçen bir kullanıcıdan gelen girdi metnidir.

Bu yazıda daha önce belirtildiği gibi, sed komut bloğunun içerdiği dizge sed tarafından kullanılan gerçek sınırlayıcıyı içeriyorsa, sed sözdizimi hatasıyla sona erer. Aşağıdaki örneği düşünün:

Bu çalışıyor:

$ VALUE=12345
$ echo "MyVar=%DEF_VALUE%" | sed -e s/%DEF_VALUE%/${VALUE}/g
MyVar=12345

Bu kırılır:

$ VALUE=12345/6
$ echo "MyVar=%DEF_VALUE%" | sed -e s/%DEF_VALUE%/${VALUE}/g
sed: -e expression #1, char 21: unknown option to `s'

Kullanıcının sınırlayıcı olarak sed tarafından kullanılan belirli karakterleri (örn. "/") Girmesini sınırlamak istemediğim için benim durumumda varsayılan sınırlayıcının değiştirilmesi sağlam bir çözüm değildir.

Bununla birlikte, giriş dizesindeki sınırlayıcının herhangi bir oluşumundan kaçmak sorunu çözecektir. Sed tarafından ayrıştırılmadan önce, giriş dizesindeki sınırlayıcı karakterden sistematik olarak kaçmanın aşağıdaki çözümünü düşünün. Bu tür kaçış, sed kullanılarak bir ikame olarak uygulanabilir, bu değiştirme, giriş dizesi sınırlayıcıyı içerse bile güvenlidir - bunun nedeni, giriş dizesinin sed komut bloğunun bir parçası olmamasıdır:

$ VALUE=$(echo ${VALUE} | sed -e "s#/#\\\/#g")
$ echo "MyVar=%DEF_VALUE%" | sed -e s/%DEF_VALUE%/${VALUE}/g
MyVar=12345/6

Bunu çeşitli komut dosyaları tarafından kullanılacak bir işleve dönüştürdüm:

escapeForwardSlashes() {

     # Validate parameters
     if [ -z "$1" ]
     then
             echo -e "Error - no parameter specified!"
             return 1
     fi

     # Perform replacement
     echo ${1} | sed -e "s#/#\\\/#g"
     return 0
}

1
Benim için cevabınızdan çıkarılacak şey, DEF_VALUE yerine kullanmakta olduğunuz DEĞER, içinde eğik çizgi varsa, VALUE="01\\\/01\\\/2018"
sed'in

3

bu satır 3 örneğin için çalışmalıdır:

sed -r 's#\?(page)=([^&]*)&#/\1/\2#g' a.txt
  • Kullandığım -rbazı kaçışa kaydedin.
  • satır bir, iki, üç durumunuz için genel olmalıdır. 3 kez alt yapmak zorunda değilsin

örneğinizle test edin (a.txt):

kent$  echo "?page=one&
?page=two&
?page=three&"|sed -r 's#\?(page)=([^&]*)&#/\1/\2#g'
/page/one
/page/two
/page/three


1

Anonim'den harika yanıt. \ HTML dizelerindeki alıntılardan kaçmaya çalıştığımda sorunumu çözdüm.

Bu nedenle, bazı HTML şablonlarını (bir sunucuda) döndürmek için sed kullanırsanız, tek yerine çift ters eğik çizgi kullanın:

var htmlTemplate = "<div style=\\"color:green;\\"></div>";

1

sedolduğunu s Team, ed in- , kendinizin kullanabileceği içinde |göndermek için (boru) standart akışları aracılığıyla (Standart giriş ve çıkışı özellikle) sedve Unix felsefesi geleneğinde bir araçtır yapım anında programlı bunları değiştirmek; ancak -iaşağıda belirtilen parametreyi kullanarak dosyaları doğrudan da düzenleyebilir .
Aşağıdakileri düşünün :

sed -i -e 's/few/asd/g' hello.txt

s/için kullanılır s Bulunan ifade yerini tutmaz fewile asd:

Az sayıda, cesur.


Asd, cesur.

/g"global" anlamına gelir, bunun anlamı tüm satır için bunu yapmaktır. /g( İle, s/few/asd/ne olursa olsun her zaman üç eğik çizgi olması gerekir) bırakırsanız fewve aynı satırda iki kez görünürseniz, yalnızca ilki fewşu şekilde değiştirilir asd:

Birkaç erkek, birkaç kadın, cesur.


Asd erkekler, birkaç kadın, cesur.

Bu, satırların başındaki özel karakterlerin değiştirilmesi gibi bazı durumlarda yararlıdır (örneğin, bazı kişilerin e-posta dizilerindeki önceki malzemeyi alıntılamak için kullandıkları daha büyük simgelerin yerine yatay bir sekme koyarken satırda alıntılanmış bir cebirsel eşitsizliği bırakarak dokunulmamış), ancak herhangi bir yerde few değiştirilmesi gerektiğini belirttiğiniz örneğinizde , buna sahip olduğunuzdan emin olun /g.

Aşağıdaki iki seçenek (işaretler) bir araya getirilmiştir -ie:

-iseçenek düzenleme için kullanılan i dosyada n yerinde hello.txt.

-eseçeneği , bu durumda çalıştırılacak e xpression / komutu belirtir s/.

Not: -i -eArama / değiştirme için kullanmanız önemlidir . Bunu yaparsanız -ie, her dosyanın yedeğini 'e' harfi eklenmiş olarak oluşturursunuz.


0

Daha basit bir alternatif, bu cevapta olduğu gibi AWK kullanmaktır :

awk '$0="prefix"$0' file > new_file


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.