Sa terminalom: Korištenje regularnih izraza II: Zamjene

U sebi prethodni članak Na osnovnom sam vam nivou rekao kako funkcionira svaki od najčešće korištenih posebnih znakova regularnih izraza. Pomoću ovih regularnih izraza moguće je obavljati složena pretraživanja u tekstualnim datotekama ili u izlazu drugih naredbi. U ovom članku ću objasniti kako pomoću naredbe sed pronaći i zamijeniti tekst na mnogo moćniji način od jednostavne promjene jednog teksta za drugi.

Još malo o naredbi grep

Prije nego što počnem govoriti o sed, želio bih malo više prokomentirati naredbu grep kako bih malo dovršio ono što je objašnjeno u prethodnom članku. Sve što ću reći bit će relevantno i za ovo. Kasnije ćemo vidjeti vezu između ovoga i pretraživanja.

Kombiniranje regularnih izraza

Mnogi posebni znakovi o kojima sam govorio u prethodnom članku mogu se kombinirati, ne samo s drugim znakovima, već i s cijelim regularnim izrazima. Način da se to učini je upotreba zagrada za formiranje podizraza. Pogledajmo primjer toga. Počnimo s preuzimanjem teksta koji možemo koristiti za testiranje. To je lista fraza. Za to ćemo koristiti sljedeću naredbu:

curl http://artigoo.com/lista-de-frases-comparativas-comicas 2>/dev/null | sed -n 's/.*\(.*\.\)<\/p>/\1/gp' > frases

 To će vas ostaviti u direktoriju u kojem pokrećete datoteku pod nazivom «fraze». Možete ga otvoriti da biste pogledali i malo se nasmijali. 🙂

Pretpostavimo sada da želimo pronaći fraze koje imaju tačno 6 riječi. Teškoća je u formiranju regularnog izraza koji odgovara svakoj riječi. Riječ je niz slova, bilo veliko ili malo, što bi bilo nešto slično '[a-zA-Z]+', ali također morate navesti da ta slova moraju biti odvojena drugim znakovima koji nisu slova, odnosno to bi bilo nešto poput '[a-zA-Z]+[^a-zA-Z]+'. Sjetimo se: "^" kao prvi znak unutar zagrada označava da se želimo podudarati sa znakovima koji nisu u rasponima, a "+" označava 1 ili više znakova.

Već imamo regularni izraz koji se može podudarati s riječju. Da biste je uparili sa 6, morat će se ponoviti 6 puta. Za to smo koristili tipke, ali beskorisno je stavljati ih '[a-zA-Z]+[^a-zA-Z]+{6}', jer bi 6 ponavljalo zadnji dio regularnog izraza i ono što želimo je da ponovimo sve, pa ono što moramo staviti je sljedeće: '([a-zA-Z]+[^a-zA-Z]+){6}'. U zagradi oblikujemo podizraz, a zagradama ponavljamo 6 puta. Sada samo trebate dodati "^" sprijeda i "$" straga kako bi odgovarao cijeloj liniji. Naredba je sljedeća:

grep -E '^([a-zA-Z]+[^a-zA-Z]+){6}$' frases

Rezultat je upravo ono što smo željeli:

Pjeva se više od Macarene. Gotovi ste od Luisa Aguiléa. Imate manje kulture od kamena. Znate više jezika od Cañita Brave. Ima više bora od Tutana Khamona. O brizi o djeci znate manje od Ramba.

Primijetite da smo stavili parametar -E jer želimo koristiti proširene regularne izraze kako bi "+" radio. Da smo koristili osnovne, morali bismo izbjeći zagrade i zagrade.

Povratne reference ili povratne reference

Ako imate instaliranu provjeru pravopisa, vjerojatno ćete imati popis riječi na jeziku /usr/share/dict/words. Ako ne, možete ga instalirati u arch sa:

sudo pacman -S words

Ili u debianu sa:

sudo aptitude install dictionaries-common

Ako želite, možete pogledati datoteku da vidite koje riječi ima. Zapravo je to veza do datoteke riječi na kojem je vaš distro. Možete istovremeno instalirati nekoliko datoteka s riječima.

Koristit ćemo tu datoteku. Ispostavilo se da smo vrlo radoznali da znamo sve palindrome od sedam slova. Za one koji ne znaju: palindrom je capicúa riječ, odnosno može se čitati s lijeva na desno kao i s desna na lijevo. Pokušajmo sa sljedećom naredbom:

grep '^\(.\)\(.\)\(.\).\3\2\1$' /usr/share/dict/words

Izgleda pomalo čudno, zar ne? Ako isprobamo, rezultat će ovisiti o jeziku vašeg distroa i riječima koje su na vašoj listi, ali u mom slučaju, kod španjolskog jezika, rezultat je sljedeći:

anilin anilin valjanje

Pogledajmo kako funkcionira ovaj regularni izraz.

Osim "^" i "$", za koje već znamo čemu služi, prvo što vidimo s lijeve strane su tri skupine točaka zatvorene u zagradama. Neka vas ne zbunjuju trake ispred svake zagrade. Trebaju pobjeći iz zagrade jer koristimo osnovne regularne izraze, ali oni nemaju drugo značenje. Važno je da tražimo bilo koja tri znaka s točkama, ali svaka od tih točaka nalazi se u zagradama. Ovo je za spremanje znakova koji se podudaraju s tim točkama kako bi se na njih ponovo moglo uputiti iz regularnog izraza. Ovo je još jedna upotreba zagrada koja će vam kasnije dobro doći za zamjenu.

Ovdje dolaze tri broja u nastavku s kosom crtom ispred sebe. U ovom slučaju, šipka je važna. Ovo znači da je donji broj pozadinska referenca i da se odnosi na jedan od prethodnih zagrada. Na primjer: \ 1 odnosi se na prvu zagradu, \ 2 na drugu itd.

Drugim riječima, sa regularnim izrazom koji smo stavili, ono što tražimo su sve riječi koje počinju s bilo koja četiri slova, a zatim imaju slovo koje je isto kao treće, drugo koje je isto kao drugo i drugo koje je isto kao prvo. Rezultat je sedam slovnih palindroma koji se nalaze na listi riječi. Baš kao što smo i željeli.

Da smo koristili proširene regularne izraze, ne bismo morali bježati iz zagrada, ali s proširenim regularnim izrazima, povratne reference ne rade u svim programima jer nisu standardizirane. Međutim, s grepom rade, pa je to možda još jedan način da to učinite. Možete probati ako želite.

Zamjenski izrazi: naredba sed

Pored pretraživanja, jedna od najboljih upotreba regularnih izraza je zamjena složenih tekstova. Da biste to učinili, jedan od načina je to pomoću naredbe sed. Moć naredbe sed ide daleko dalje od zamjene teksta, ali ovdje ću ga iskoristiti za to. Sintaksa koju ću koristiti s ovom naredbom je sljedeća:

sed [-r] 's/REGEX/REPL/g' FICHERO

Ili takođe:

COMANDO | sed [-r] 's/REGEX/REPL/g'

Gdje će REGEX biti regularni izraz pretraživanja, a REPL zamjena. Imajte na umu da ova naredba zapravo ne zamjenjuje ništa u datoteci koju naznačimo, ali ono što pokazuje je da nam pokazuje rezultat zamjene u terminalu, zato se nemojte bojati naredbi koje ću sljedeće staviti. Nijedan od njih neće modificirati nijednu datoteku na vašem sistemu.

Počnimo sa jednostavnim primjerom. Svi imamo razne konfiguracijske datoteke u direktorijumu / etc koje obično imaju komentare koji počinju sa "#". Pretpostavimo da želimo vidjeti jednu od ovih datoteka bez komentara. Na primjer, to ću učiniti s fstab-om. Možete probati s onim kojeg želite.

sed 's/#.*//g' /etc/fstab

Neću ovdje stavljati rezultat naredbe, jer to ovisi o tome što imate u vašem fstabu, ali ako uporedite izlaz naredbe sa sadržajem datoteke, vidjet ćete da su svi komentari nestali.

U ovoj naredbi izraz za pretraživanje je «#.*", To je" # "iza kojeg slijedi bilo koji broj znakova, odnosno komentari. A zamjenski izraz, ako pogledate dvije trake zaredom, vidjet ćete da ih nema, pa ono što radi je zamjena komentara ničim, odnosno njihovo brisanje. Jednostavnije nemoguće.

Sada ćemo učiniti suprotno. Pretpostavimo da ono što želimo je da komentiramo sve redove datoteke. Pokušajmo ovako:

sed 's/^/# /g' /etc/fstab

Vidjet ćete da u izlazu naredbe sve linije započinju oznakom hash i praznim razmakom. Ono što smo učinili je zamijeniti početak retka sa «# «. Ovo je također prilično jednostavan primjer gdje je tekst koji treba zamijeniti uvijek isti, ali sada ćemo ga malo zakomplicirati.

Blagodat zamjena je u tome što u izrazu zamjene možete koristiti povratne reference poput onih koje sam vam već rekao. Vratimo se datoteci fraza koju smo preuzeli na početku članka. U zagrade ćemo staviti sva velika slova koja postoje, ali to ćemo učiniti naredbom:

sed 's/\([A-Z]\)/(\1)/g' frases

Ovdje imamo povratno pozivanje u zamjenskom izrazu koji se odnosi na zagrade u izrazu za pretraživanje. Zagrade u zamjenskom izrazu su normalne zagrade. U zamjenskom izrazu nemaju posebno značenje, stavljaju se takvi kakvi jesu. Rezultat je da se sva velika slova zamjenjuju istim tim slovom, bilo kojim, sa zagradama oko njega.

Postoji još jedan znak koji se također može koristiti u zamjenskom izrazu, to je "&" i zamjenjuje ga sav tekst koji se podudara s izrazom za pretraživanje. Primjer za to može biti stavljanje svih fraza u datoteku pod navodnike. To se može postići ovom naredbom:

sed 's/.*/"&"/g' frases

Rad ove naredbe vrlo je sličan prethodnoj, samo što sada zamjenjujemo cijelu liniju s istom linijom s navodnicima oko nje. Budući da koristimo "&", nije potrebno stavljati zagrade.

Neke korisne naredbe s regularnim izrazima

Evo nekoliko naredbi koje smatram korisnima ili znatiželjnima i koje koriste regularne izraze. Pomoću ovih naredbi korisnost regularnih izraza je mnogo bolja nego kod primjera koje sam vam do sada dao, ali činilo mi se važnim objasniti nešto o tome kako regularni izrazi rade kako bi ih razumjeli.

  • Prikaži odjeljke man stranice:

man bash | grep '^[A-Z][A-Z ]*$'

Naravno, možete promijeniti naredbu bash u bilo što što želite. A onda od čovjeka možete ići direktno u odjeljak koji vas zanima koristeći, naravno, regularni izraz. Pritisnite «/» za početak pretraživanja i pisanja «^ALIASES$»Da odete, na primjer, u odjeljak ALIASES. Mislim da je ovo prva upotreba regularnih izraza koju sam počeo koristiti prije nekoliko godina. Kretanje kroz neke stranice priručnika gotovo je nemoguće bez ovakvog trika.

  • Pokažite imena svih korisnika mašine, uključujući posebne:

sed 's/\([^:]*\).*/\1/' /etc/passwd

  • Prikaži korisnička imena, ali samo ona s ljuskom:

grep -vE '(/false|/nologin)$' /etc/passwd | sed 's/\([^:]*\).*/\1/g'

To se zaista može učiniti jednim regularnim izrazom, ali način na koji to ide prevazilazi ono što sam vam rekao u ovim člancima, pa sam to učinio kombiniranjem dvije naredbe.

  • U zadnju tri znamenke svih brojeva umetnite zarez u datoteku brojeva:

sed 's/\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)/\1\2,\3/g' numbers

Radi samo s brojevima do 6 znamenki, ali može se pozvati više puta da se odvajači postave u ostale grupe od tri znamenke.

  •  Izdvojite sve adrese e-pošte iz datoteke:

grep -E '\<[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}\>' FICHERO

  • Odvojite dan, mjesec i godinu svih datuma koji se pojavljuju u datoteci:

sed -r 's/([0-9]{2})[/-]([0-9]{2})[/-]([0-9]{4})/Día: \1, Mes: \2, Año: \3/g' FICHERO

  • Saznajte našu lokalnu IP adresu:

/sbin/ifconfig | grep 'inet .*broadcast' | sed -r 's/[^0-9]*(([0-9]+\.){3}[0-9]+).*/\1/g'

To se također može učiniti jednom naredbom sed, ali za jednostavnost je bolje da je razdvojim na grep i sed.

Neke korisne adrese

Evo nekoliko adresa koje mogu biti korisne u vezi sa regularnim izrazima:

  • Biblioteka regularnih izraza: Ovo je biblioteka regularnih izraza u kojoj možete pretraživati ​​regularne izraze povezane s temom koja vas zanima. Da biste tražili web adrese, ID ili bilo što drugo.
  • RegExr: Mrežna provjera regularnih izraza. Omogućava vam da unesete tekst i primijenite regularni izraz na njega ili pretražite ili zamijenite. Daje informacije o regularnom izrazu i imate nekoliko mogućnosti da promijenite njegovo ponašanje.
  • Tester regularnih izraza: To je dodatak za firefox koji omogućava provjeru regularnih izraza iz preglednika.

zaključak

Za sada je to sve. Regularni izrazi su složeni, ali korisni. Potrebno je vrijeme da ih naučite, ali ako ste poput mene, igranje s njima činit će se zabavno i malo po malo savladaćete ih. To je cijeli svijet. Još uvijek možemo puno toga reći o lijenim kvantifikatorima, regularnom izrazu u PERL stilu, višerednom itd. I tada svaki program ima svoje karakteristike i svoje varijante, pa je najbolji savjet koji vam mogu dati uvijek pogledati dokumentaciju programa koju koristite svaki put kad morate napisati regularni izraz u novom programu.

Hej! ... HEJ! … PROBUDI SE! ... ŠTA SVE SPAVATE? 🙂

Fuentes

Neke od ideja i primjera za regularne izraze u ovom članku preuzeo sam odavde:


Ostavite komentar

Vaša e-mail adresa neće biti objavljena. Obavezna polja su označena sa *

*

*

  1. Za podatke odgovoran: Miguel Ángel Gatón
  2. Svrha podataka: Kontrola neželjene pošte, upravljanje komentarima.
  3. Legitimacija: Vaš pristanak
  4. Komunikacija podataka: Podaci se neće dostavljati trećim stranama, osim po zakonskoj obavezi.
  5. Pohrana podataka: Baza podataka koju hostuje Occentus Networks (EU)
  6. Prava: U bilo kojem trenutku možete ograničiti, oporaviti i izbrisati svoje podatke.

  1.   živahno rekao je

    Majstorski !!!

    1.    hexborg rekao je

      Nije tako loše, ali hvala vam puno. Nadam se da će se ljudima svidjeti. 🙂

      1.    oscar rekao je

        Sviđa mi se ha!

        1.    hexborg rekao je

          Onda sam sigurno nešto dobro uradio. LOL!! 🙂

          Puno vam hvala na komentaru.

          1.    Blaire pascal rekao je

            Jebi, nastavi pisati, nastavi tako.

          2.    hexborg rekao je

            @Blaire Pascal: Komentari poput vašeg to ohrabruju. 🙂 Hvala vam puno !!

      2.    Grad rekao je

        I meni se svidjelo ... hvala 🙂

        1.    hexborg rekao je

          Hvala vam na komentaru. Nadam se da ću napisati još nekoliko. 🙂

  2.   mariano rekao je

    Vaše objave su fantastične, naučite puno, nego naučite izvršavati zadatke na elegantan i efikasan način.

    Jeste li razmišljali o prikupljanju svih svojih postova u skriptu ljuske? Poredano u pdf formatu bio bi sjajan priručnik.

    Živjeli i hvala vam puno!

    1.    hexborg rekao je

      Hvala puno!! To nije loša ideja. Trenutno su samo dvije, ali o tome ću razmisliti kasnije. 🙂

  3.   Kiyov rekao je

    vrlo dobar članak, 5+.

    1.    hexborg rekao je

      Hvala ti. Drago mi je da ti se sviđa. 🙂

  4.   sebastian rekao je

    Odlicno! Moram promijeniti sljedeći izraz, a ne znam kako to učiniti:
    192.168.0.138/Server od 192.168.0.111/data
    Problem leži u simbolu "/".
    Koristim naredbu:
    pronađi. -ime "* .txt" -exec sed -i 's / TEXT1 / TEXT2 / g' {} \;
    Šta se koristi za izvršavanje ove vrste zadataka sa zaostatkom, ali ne mogu ...
    Zna li neko kako bih to trebao učiniti?
    Zagrljaj!
    Seba

    1.    hexborg rekao je

      Ono što morate učiniti je pobjeći liku poput ovog:

      pronađi. -ime "* .txt" -exec sed -i 's / \ / Server / \ / data / g' {} \;

      Možete koristiti i drugi separator u sed. Ne mora biti bar. Sed dozvoljava upotrebu bilo kojeg lika. Na primjer, ovo bi bilo jasnije:

      pronađi. -ime "* .txt" -exec sed -i 's | / Server | / podaci | g' {} \;

      A ako ćete kopirati i zalijepiti naredbe iz ovog komentara, budite oprezni s navodnicima, koji ih Wordpress mijenja u tipografske. 🙂

      Pozdrav.

  5.   sebastian rekao je

    Odlicno !!!!
    Dugo sam tražio ovo rješenje.
    Ovdje ostavljam kompletnu naredbu koju sam koristio

    pronađi. -ime "* .txt" -exec sed -i | 192 \ .168 \ .0 \ .238 \ / Server | 192 \ .168 \ .0 \ .111 \ / data | g '{} \;

    Prednost ove naredbe je u tome što rekurzivno mijenja sve .txt datoteke (ili ekstenziju koju želite) ... Morate biti vrlo oprezni!
    Ali vrlo je korisno !!!

    Pa, hvala na svemu i hiljadu čestitki cijeloj grupi.
    Uvijek ih čitam sa pošte!
    Zagrljaji
    Seba