İçimde önceki haber Düzenli ifadelerin en çok kullanılan özel karakterlerinin her birinin nasıl çalıştığını temel düzeyde anlattım. Bu normal ifadelerle, metin dosyalarında veya diğer komutların çıktılarında karmaşık aramalar yapmak mümkündür. Bu makalede, metni bulmak ve değiştirmek için sed komutunun, bir metni diğeriyle değiştirmekten çok daha güçlü bir şekilde nasıl kullanılacağını açıklayacağım.
Grep komutu hakkında biraz daha
Sed hakkında konuşmaya başlamadan önce, bir önceki makalede anlatılanları biraz tamamlamak adına grep komutu hakkında biraz daha yorum yapmak istiyorum. Söyleyeceğim her şey bununla da alakalı olacak. Daha sonra bununla aramalar arasındaki ilişkiyi göreceğiz.
Normal ifadeleri birleştirmek
Önceki makalede bahsettiğim özel karakterlerin çoğu, yalnızca diğer karakterlerle değil, tüm normal ifadelerle birleştirilebilir. Bunu yapmanın yolu, bir alt ifade oluşturmak için parantez kullanmaktır. Bunun bir örneğini görelim. Test için kullanabileceğimiz bir metin indirerek başlayalım. İfadelerin bir listesidir. Bunun için aşağıdaki komutu kullanacağız:
curl http://artigoo.com/lista-de-frases-comparativas-comicas 2>/dev/null | sed -n 's/.*\(.*\.\)<\/p>/\1/gp' > frases
Bu sizi, «sözcük öbekleri» adıyla bir dosyayı açtığınız dizinde bırakacaktır. Bir göz atmak ve biraz gülmek için onu açabilirsiniz. 🙂
Şimdi, tam olarak 6 kelimeden oluşan cümleleri bulmak istediğimizi varsayalım. Zorluk, her kelimeyle eşleşen düzenli bir ifade oluşturmaktır. Bir kelime, büyük veya küçük harflerden oluşan bir dizidir; '[a-zA-Z]+'
, ancak bu harflerin harflerden başka karakterlerle ayrılması gerektiğini de belirtmelisiniz, yani '[a-zA-Z]+[^a-zA-Z]+'
. Unutmayın: Parantez içindeki ilk karakter olarak "^", aralıklarda olmayan karakterlerle eşleştirmek istediğimizi belirtir ve "+" 1 veya daha fazla karakteri gösterir.
Zaten bir kelimeyle eşleşebilecek normal bir ifademiz var. 6 ile eşleştirmek için 6 kez tekrarlanması gerekecektir. Bunun için anahtarları kullandık, ama koymak faydasız '[a-zA-Z]+[^a-zA-Z]+{6}'
, çünkü 6, düzenli ifadenin son bölümünü tekrar ederdi ve istediğimiz, hepsini tekrarlamaktır, bu yüzden koymamız gereken şey şudur: '([a-zA-Z]+[^a-zA-Z]+){6}'
. Parantezlerle bir alt ifade oluşturuyoruz ve parantezlerle bunu 6 kez tekrarlıyoruz. Şimdi tüm satırı eşleştirmek için önüne bir "^" ve arkaya bir "$" eklemeniz yeterlidir. Komut aşağıdaki gibidir:
grep -E '^([a-zA-Z]+[^a-zA-Z]+){6}$' frases
Ve sonuç tam da istediğimiz şeydi:
Macarena'dan daha çok söylenir. Luis Aguilé'den daha işin bitti. Bir taştan daha az kültüre sahipsin. Cañita Brava'dan daha fazla dil biliyorsunuz. Tutan Khamón'dan daha fazla kırışıklığı var. Çocuk bakımı hakkında Rambo'dan daha az şey biliyorsun.
"+" İşlevinin çalışmasını sağlamak için genişletilmiş normal ifadeler kullanmak istediğimiz için -E parametresini koyduğumuza dikkat edin. Temel olanları kullanırsak, parantezlerden ve parantezlerden kaçmamız gerekirdi.
Geri referanslar veya geri referanslar
Yüklü bir yazım denetleyiciniz varsa, muhtemelen bir kelime listeniz olacaktır. /usr/share/dict/words
. Değilse, aşağıdakilerle arch'a kurabilirsiniz:
sudo pacman -S words
Veya debian'da şununla:
sudo aptitude install dictionaries-common
İsterseniz dosyada hangi kelimelerin olduğunu görmek için dosyaya bakabilirsiniz. Aslında dağıtımınızın bulunduğu dilin kelime dosyasına bir bağlantıdır. Aynı anda birkaç kelime dosyası kurabilirsiniz.
O dosyayı kullanacağız. Dışarıdaki yedi harfli palindromun tümünü bilmek bizi çok merak ediyor. Bilmeyenler için: Palindrom bir kapicúa kelimedir, yani soldan sağa ve sağdan sola okunabilir. Şu komutu deneyelim:
grep '^\(.\)\(.\)\(.\).\3\2\1$' /usr/share/dict/words
Biraz tuhaf görünüyor, değil mi? Eğer denersek, sonuç dağıtımınızın diline ve listenizdeki kelimelere bağlı olacaktır, ancak benim durumumda İspanyolca dilinde sonuç şudur:
anilin anilin haddeleme
Bu normal ifadenin nasıl çalıştığını görelim.
Ne için olduğunu zaten bildiğimiz "^" ve "$" dışında, solda gördüğümüz ilk şey parantez içine alınmış üç nokta grubudur. Her parantezin önündeki çubuklar kafanızı karıştırmasın. Temel normal ifadeleri kullandığımız için parantezlerden kaçacaklardır, ancak başka anlamları yoktur. Önemli olan, noktalı herhangi bir üç karakter istememizdir, ancak bu noktaların her biri parantez içine alınmıştır. Bu, bu noktalarla eşleşen karakterleri, normal ifadeden tekrar başvurulabilecek şekilde kaydetmek içindir. Bu, daha sonra değişiklik yaparken kullanışlı olacak başka bir parantez kullanımıdır.
Bu, aşağıdaki üç sayının önlerinde eğik çizgi ile geldiği yerdir. Bu durumda çubuk önemlidir. Aşağıdaki sayının bir geri referans olduğunu ve önceki parantezlerden birine atıfta bulunduğunu belirtmek için kullanılır. Örneğin: \ 1 ilk paranteze, \ 2 ikinciye ve bu böyle devam eder.
Yani, koyduğumuz normal ifadeyle, aradığımız şey, herhangi bir dört harfle başlayan ve ardından üçüncüyle aynı, ikincisi ve diğeriyle aynı olan başka bir harfe sahip olan tüm kelimelerdir. bu ilkiyle aynı. Sonuç, kelime listesindeki yedi harfli palindromlardır. Tam istediğimiz gibi.
Genişletilmiş düzenli ifadeler kullanıyor olsaydık, parantezlerden kaçmak zorunda kalmazdık, ancak genişletilmiş normal ifadelerle geri başvurular, standartlaştırılmadıkları için tüm programlarda çalışmaz. Bununla birlikte, grep ile çalışırlar, bu yüzden aynı şeyi yapmanın başka bir yolu olabilir. İstersen deneyebilirsin.
Değiştirme ifadeleri: sed komutu
Aramaya ek olarak, normal ifadelerin en iyi kullanımlarından biri karmaşık metinleri değiştirmektir. Bunu yapmanın bir yolu sed komutudur. Sed komutunun gücü, metni değiştirmenin çok ötesine geçer, ancak burada bunun için kullanacağım. Bu komutla kullanacağım sözdizimi şu şekildedir:
sed [-r] 's/REGEX/REPL/g' FICHERO
Veya:
COMANDO | sed [-r] 's/REGEX/REPL/g'
REGEX, arama normal ifadesi olacak ve yerine geçeni REPL olacaktır. Bu komutun, belirttiğimiz dosyadaki hiçbir şeyin yerini almadığını unutmayın, ancak yaptığı şey bize terminaldeki değiştirmenin sonucunu göstermektir, bu nedenle daha sonra koyacağım komutlardan korkmayın. Hiçbiri sisteminizdeki herhangi bir dosyayı değiştirmeyecek.
Basit bir örnekle başlayalım. Hepimizin / etc dizininde, genellikle "#" ile başlayan açıklamaları olan çeşitli yapılandırma dosyaları vardır. Bu dosyalardan birini yorumlar olmadan görmek istediğimizi varsayalım. Örneğin, bunu fstab ile yapacağım. İstediğinle deneyebilirsin.
sed 's/#.*//g' /etc/fstab
Komutun sonucunu buraya koymayacağım çünkü fstab'ınızda neye sahip olduğunuza bağlı, ancak komutun çıktısını dosyanın içeriği ile karşılaştırırsanız tüm yorumların kaybolduğunu göreceksiniz.
Bu komutta arama ifadesi «#.*
", Bu bir" # "ve ardından herhangi bir sayıda karakter, yani yorumlar gelir. Ve değiştirme ifadesi, arka arkaya iki çubuğa bakarsanız, hiçbirinin olmadığını görürsünüz, bu yüzden yaptığı şey yorumları hiçbir şeyle değiştirmek, yani onları silmek. Daha basit imkansız.
Şimdi tam tersini yapacağız. Diyelim ki istediğimiz dosyanın tüm satırları hakkında yorum yapmaktır. Şöyle deneyelim:
sed 's/^/# /g' /etc/fstab
Komut çıktısında, tüm satırların bir hash işareti ve bir boşlukla başladığını göreceksiniz. Yaptığımız şey satırın başlangıcını «ile değiştirmek.#
«. Bu aynı zamanda, değiştirilecek metnin her zaman aynı olduğu oldukça basit bir örnektir, ancak şimdi onu biraz daha karmaşık hale getireceğiz.
Değiştirmelerin lütfu, değiştirme ifadesinde size daha önce söylediğim gibi geri referansları kullanabilmenizdir. Makalenin başında indirdiğimiz cümle dosyasına geri dönelim. Tüm büyük harfleri parantez içine alacağız, ancak bunu bir komutla yapacağız:
sed 's/\([A-Z]\)/(\1)/g' frases
Burada sahip olduğumuz şey, arama ifadesindeki parantezlere atıfta bulunan değiştirme ifadesinde bir geri referanstır. Değiştirme ifadesindeki parantezler normal parantezlerdir. Değiştirme ifadesinde özel bir anlamı yoktur, olduğu gibi konurlar. Sonuç olarak, tüm büyük harfler, her neyse, etraflarında parantez bulunan aynı harfle değiştirilir.
Yerine koyma ifadesinde de kullanılabilecek başka bir karakter vardır, bu "&" dir ve arama ifadesiyle eşleşen tüm metinle değiştirilir. Bunun bir örneği, dosyadaki tüm cümleleri tırnak içine almak olabilir. Bu, şu komutla gerçekleştirilebilir:
sed 's/.*/"&"/g' frases
Bu komutun işleyişi öncekine çok benzer, ancak şimdi değiştirdiğimiz şey, aynı satırın etrafında tırnaklar bulunan tüm satırıdır. "&" Kullandığımız için parantez koymaya gerek yoktur.
Normal ifadelere sahip bazı yararlı komutlar
İşte yararlı veya meraklı bulduğum ve normal ifadeler kullanan birkaç komut. Bu komutlarla, düzenli ifadelerin faydası şimdiye kadar verdiğim örneklerden çok daha iyidir, ancak onları anlamak için normal ifadelerin nasıl çalıştığına dair bir şeyler açıklamak benim için önemli göründü.
- Bir man sayfasının bölümlerini göster:
man bash | grep '^[A-Z][A-Z ]*$'
Elbette, bash komutunu istediğiniz gibi değiştirebilirsiniz. Ve sonra erkekten, sizi ilgilendiren bölüme doğrudan gidebilirsiniz, tabii ki, normal bir ifade kullanarak. Aramaya başlamak ve «yazmak için« / »düğmesine basın^ALIASES$
»Örneğin ALIASES bölümüne gitmek için. Sanırım birkaç yıl önce düzenli ifadelerden yapmaya başladığım ilk kullanım bu. Kılavuzun bazı sayfalarında böyle bir numara olmadan dolaşmak neredeyse imkansızdır.
- Özel olanlar dahil makinenin tüm kullanıcılarının adlarını gösterin:
sed 's/\([^:]*\).*/\1/' /etc/passwd
- Kullanıcı adlarını göster, ancak yalnızca kabuğu olanlar:
grep -vE '(/false|/nologin)$' /etc/passwd | sed 's/\([^:]*\).*/\1/g'
Gerçekten tek bir düzenli ifade ile yapılabilir, ancak bunu yapmanın yolu bu makalelerde anlattığımın ötesine geçiyor, bu yüzden bunu iki komutu birleştirerek yaptım.
- Sayılar dosyasındaki tüm sayıların son üç basamağından önce bir virgül ekleyin:
sed 's/\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)/\1\2,\3/g' numbers
Yalnızca 6 basamağa kadar olan sayılarla çalışır, ancak diğer üç basamaklı gruplara ayırıcı yerleştirmek için birden çok kez çağrılabilir.
- Bir dosyadan tüm e-posta adreslerini çıkarın:
grep -E '\<[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}\>' FICHERO
- Bir dosyada görünen tüm tarihlerin gününü, ayını ve yılını ayırın:
sed -r 's/([0-9]{2})[/-]([0-9]{2})[/-]([0-9]{4})/Día: \1, Mes: \2, Año: \3/g' FICHERO
- Yerel IP adresimizi bulun:
/sbin/ifconfig | grep 'inet .*broadcast' | sed -r 's/[^0-9]*(([0-9]+\.){3}[0-9]+).*/\1/g'
Bu aynı zamanda tek bir sed komutuyla da yapılabilir, ancak basit olması için onu grep ve sed olarak ayırmalıyım.
Bazı yararlı adresler
Normal ifadelerle ilgili faydalı olabilecek bazı adresler şunlardır:
- Normal ifade kitaplığı: Sizi ilgilendiren konuyla ilgili düzenli ifadeleri arayabileceğiniz normal bir ifade kitaplığıdır. Web adreslerini, kimliği veya her neyse aramak için.
- Normal İfade: Çevrimiçi bir düzenli ifade denetleyicisi. Bir metin girmenize ve ona arama veya değiştirme gibi bir normal ifade uygulamanıza olanak tanır. Normal ifade hakkında bilgi verir ve davranışını değiştirmek için birkaç seçeneğiniz vardır.
- Normal İfadeler Test Cihazı: Tarayıcıdan normal ifadeleri kontrol etmeye izin veren bir firefox eklentisidir.
Sonuç
Şimdilik hepsi bu. Normal ifadeler karmaşıktır ancak kullanışlıdır. Bunları öğrenmek zaman alır, ancak benim gibiyseniz, onlarla oynamak eğlenceli görünecek ve yavaş yavaş onlara hakim olacaksınız. Bu bütün bir dünya. Tembel niceleyiciler, PERL tarzı düzenli ifade, çok satırlı vb. Ve sonra her programın kendine has özellikleri ve çeşitleri vardır, bu yüzden size verebileceğim en iyi tavsiye, her zaman yeni bir programda düzenli bir ifade yazmanız gerektiğinde kullandığınız programın belgelerine bakmaktır.
Hey! …HEY! … UYANMAK! … HEPİNİZ NE YAPIYORSUNUZ? 🙂
Fuentes
Buradan aldığım bu makaledeki normal ifadeler için bazı fikirler ve örnekler:
- http://sed.sourceforge.net/sed1line.txt
- http://www.thegeekstuff.com/2009/10/unix-sed-tutorial-advanced-sed-substitution-examples/
Ustaca !!!
O kadar da kötü değil ama çok teşekkür ederim. Umarım insanlar beğenir. 🙂
Bunu beğendim ha!
O zaman doğru bir şey yapmış olmalıyım. LOL !! 🙂
Yorumunuz için çok teşekkür ederim.
Yazmaya devam et adamım, devam et.
@Blaire Pascal: Sizinki gibi yorumlar onu teşvik eder. 🙂 Çok teşekkür ederim !!
Ben de beğendim ... teşekkürler 🙂
Yorum için teşekkürler. Birkaç tane daha yazmayı umuyorum. 🙂
Gönderileriniz harika, çok şey öğreniyorsunuz, bunun yerine görevleri zarif ve verimli bir şekilde yapmayı öğreniyorsunuz.
Tüm kabuk komut dosyası gönderilerinizi toplamayı düşündünüz mü? Bir pdf olarak sıralamak harika bir kılavuz olur.
Neşeleniyor ve çok teşekkür ederim!
Çok teşekkür ederim!! Fena fikir değil. Şu anda sadece iki tane var ama bunu daha sonra düşüneceğim. 🙂
çok iyi makale, 5+.
Teşekkür ederim. Beğenmene sevindim. 🙂
Mükemmel! Aşağıdaki ifadeyi değiştirmem gerekiyor ve bunu nasıl yapacağımı bilmiyorum:
192.168.0.138/Server, 192.168.0.111/data tarafından
Sorun "/" sembolünde yatıyor.
Şu komutu kullanıyorum:
bul. -name "* .txt" -exec sed -i 's / TEXT1 / TEXT2 / g' {} \;
Bu tür bir görevi ihmal ederek yerine getirmek için kullanılan, ama yapamam ...
Bunu nasıl yapmam gerektiğini bilen var mı?
Hug!
Sheba
Yapmanız gereken şey şu şekilde karakterden kaçmak:
bul. -name "* .txt" -exec sed -i 's / \ / Sunucu / \ / veri / g' {} \;
Sed'de başka bir ayırıcı da kullanabilirsiniz. Bar olmak zorunda değil. Sed, herhangi bir karakterin kullanılmasına izin verir. Örneğin, bu daha net olacaktır:
bul. -name "* .txt" -exec sed -i 's | / Sunucu | / veri | g' {} \;
Ve bu yorumdaki komutları kopyalayıp yapıştıracaksanız, alıntılara dikkat edin, bu wordpress onları tipografik olanlar için değiştirir. 🙂
Selamlar.
Mükemmel!!!!
Bu çözümü uzun zamandır arıyordum.
Burada kullandığım tam komutu bırakıyorum
bul. -name "* .txt" -exec sed -i 's | 192 \ .168 \ .0 \ .238 \ / Server | 192 \ .168 \ .0 \ .111 \ / data | g' {} \;
Bu komutun avantajı, tüm .txt dosyalarını (veya istediğiniz uzantıyı) özyinelemeli olarak değiştirmesidir ... Çok dikkatli olmalısınız!
Ama çok kullanışlı !!!
Her şey için teşekkürler ve tüm gruba binlerce tebrik.
Onları her zaman postadan okurum!
sarılmalar
Sheba