Terminal ile: Normal İfadeleri Kullanma II: Değiştirmeler

İç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:


Yorumunuzu bırakın

E-posta hesabınız yayınlanmayacak. Gerekli alanlar ile işaretlenmiştir *

*

*

  1. Verilerden sorumlu: Miguel Ángel Gatón
  2. Verilerin amacı: Kontrol SPAM, yorum yönetimi.
  3. Meşruiyet: Onayınız
  4. Verilerin iletilmesi: Veriler, yasal zorunluluk dışında üçüncü kişilere iletilmeyecektir.
  5. Veri depolama: Occentus Networks (AB) tarafından barındırılan veritabanı
  6. Haklar: Bilgilerinizi istediğiniz zaman sınırlayabilir, kurtarabilir ve silebilirsiniz.

  1.   ela dijo

    Ustaca !!!

    1.    Hexborg dijo

      O kadar da kötü değil ama çok teşekkür ederim. Umarım insanlar beğenir. 🙂

      1.    Oskar dijo

        Bunu beğendim ha!

        1.    Hexborg dijo

          O zaman doğru bir şey yapmış olmalıyım. LOL !! 🙂

          Yorumunuz için çok teşekkür ederim.

          1.    Blaire pascal dijo

            Yazmaya devam et adamım, devam et.

          2.    Hexborg dijo

            @Blaire Pascal: Sizinki gibi yorumlar onu teşvik eder. 🙂 Çok teşekkür ederim !!

      2.    Şehir dijo

        Ben de beğendim ... teşekkürler 🙂

        1.    Hexborg dijo

          Yorum için teşekkürler. Birkaç tane daha yazmayı umuyorum. 🙂

  2.   mariano dijo

    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!

    1.    Hexborg dijo

      Çok teşekkür ederim!! Fena fikir değil. Şu anda sadece iki tane var ama bunu daha sonra düşüneceğim. 🙂

  3.   Kiev dijo

    çok iyi makale, 5+.

    1.    Hexborg dijo

      Teşekkür ederim. Beğenmene sevindim. 🙂

  4.   sebastian dijo

    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

    1.    Hexborg dijo

      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.

  5.   sebastian dijo

    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