S terminalom: Korištenje regularnih izraza II: Zamjene

U Sebi artículo prednji Na osnovnoj sam vam razini rekao kako funkcionira svaki od najčešće korištenih posebnih znakova regularnih izraza. Pomoću ovih regularnih izraza moguće je složeno pretraživanje u tekstualnim datotekama ili u izlazu drugih naredbi. U ovom ću članku objasniti kako upotrijebiti naredbu sed za pronalaženje i zamjenu teksta na mnogo moćniji način od jednostavne promjene jednog teksta za drugi.

Još malo o naredbi grep

Prije nego što započnem govoriti o sed, želio bih malo više komentirati 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 oblikovanje podizraza. Pogledajmo primjer toga. Krenimo s preuzimanjem teksta koji možemo koristiti za testiranje. To je popis fraza. Za to ćemo upotrijebiti 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 kako biste pogledali i malo se nasmijali. 🙂

Sad pretpostavimo da želimo pronaći fraze koje imaju točno 6 riječi. Teškoća je u oblikovanju 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 osim slova, to bi bilo nešto slično '[a-zA-Z]+[^a-zA-Z]+'. Zapamtite: "^" 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 '[a-zA-Z]+[^a-zA-Z]+{6}', jer bi 6 ponavljalo zadnji dio regularnog izraza, a ono što želimo je ponoviti sve, pa ono što moramo staviti je sljedeće: '([a-zA-Z]+[^a-zA-Z]+){6}'. U zagradi oblikujemo podizraz i u zagradama ga ponavljamo 6 puta. Sada samo trebate dodati "^" sprijeda i "$" straga kako bi odgovarao cijelom retku. Naredba je sljedeća:

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

A 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ñite 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 u /usr/share/dict/words. Ako ne, možete ga instalirati u arch s:

sudo pacman -S words

Ili u debianu sa:

sudo aptitude install dictionaries-common

Ako želite, možete pogledati datoteku da biste vidjeli koje riječi ima. To je zapravo veza do datoteke riječi za jezik na kojem je vaš distro. Možete istodobno instalirati nekoliko datoteka s riječima.

Koristit ćemo tu datoteku. Ispada da smo vrlo znatiželjni znati sve palindrome od sedam slova vani. 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 s vašeg popisa, ali u mom slučaju, za španjolski jezik, 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 zbune trake ispred svake zagrade. Trebaju pobjeći iz zagrade jer se koristimo osnovnim regularnim izrazima, 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 ponovno moglo uputiti iz regularnog izraza. Ovo je još jedna upotreba zagrada koja će vam kasnije dobro doći za zamjenu.

Ovdje dolaze tri donja broja s kosom crtom ispred sebe. U ovom slučaju, šipka je važna. Koristi se za označavanje da je donji broj pozadinska referenca i da se odnosi na jednu od prethodnih zagrada. Na primjer: \ 1 odnosi se na prvu zagradu, \ 2 na drugu itd.

Drugim riječima, uz regularni izraz 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 drugi koji je isti kao i prvi. Rezultat je sedam slovnih palindroma koji se nalaze na popisu riječi. Baš onako kako smo htjeli.

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 naredbom sed. Moć naredbe sed daleko nadilazi zamjenu 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đer:

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 pokazuje nam rezultat zamjene u terminalu, zato se nemojte bojati naredbi koje ću sljedeće staviti. Nitko od njih neće izmijeniti nijednu datoteku na vašem sustavu.

Počnimo s jednostavnim primjerom. Svi imamo razne konfiguracijske datoteke u direktoriju / etc koje obično imaju komentare koji počinju s "#". Pretpostavimo da jednu od ovih datoteka želimo vidjeti bez komentara. Na primjer, učinit ću to s fstabom. Možete pokušati 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 usporedite 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. I 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 jest komentirati sve retke datoteke. Pokušajmo ovako:

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

Vidjet ćete da u izlazu naredbe svi retci počinju s oznakom raspršivanja i praznim prostorom. 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 za zamjenu 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 učinit ćemo to naredbom:

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

Ovdje imamo povratnu referencu 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, s 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 u 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 cijeli redak s istim retkom s navodnicima oko njega. 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. S ovim naredbama korisnost regularnih izraza je puno bolja nego s primjerima koje sam do sada davao, 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 na bilo što što želite. A onda od čovjeka možete ići izravno u odjeljak koji vas zanima koristeći, naravno, regularni izraz. Pritisnite «/» za početak pretraživanja i pisanja «^ALIASES$»Da biste, primjerice, otišli 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.

  • Prikažite imena svih korisnika stroja, 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 doista može učiniti jednim regularnim izrazom, ali način na koji to ide nadilazi ono što sam vam rekao u ovim člancima, pa sam to učinio kombinirajući 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 za postavljanje odvajača u ostale skupine 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

  • Doznajte 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 u grep i sed.

Neke korisne adrese

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

  • Biblioteka regularnih izraza: To 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ćuje 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.
  • Ispitivač regularnih izraza: To je dodatak za firefox koji omogućuje 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 zabavnim i, malo po malo, svladavat ćete ih. To je cijeli svijet. Još bi se puno toga moglo 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 u novi program morate unijeti regularni izraz.

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

izvori

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


Ostavite svoj komentar

Vaša email adresa neće biti objavljen. Obavezna polja su označena s *

*

*

  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 obvezi.
  5. Pohrana podataka: Baza podataka koju hostira Occentus Networks (EU)
  6. Prava: U bilo kojem trenutku možete ograničiti, oporaviti i izbrisati svoje podatke.

  1.   živo dijo

    Majstorski!!!

    1.    hexborg dijo

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

      1.    Oscar dijo

        Sviđa mi se ha!

        1.    hexborg dijo

          Onda sam sigurno nešto dobro učinio. LOL!! 🙂

          Puno vam hvala na komentaru.

          1.    Blaire pascal dijo

            Jebi, nastavi pisati čovječe, nastavi tako.

          2.    hexborg dijo

            @Blaire Pascal: Komentari poput vašeg to potiču. 🙂 veliko hvala !!

      2.    Grad dijo

        I meni se svidjelo ... hvala 🙂

        1.    hexborg dijo

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

  2.   Marian dijo

    Vaši su postovi fantastični, naučite puno, nego naučite izvršavati zadatke na elegantan i učinkovit način.

    Jeste li razmišljali o prikupljanju svih svojih postova u skriptu ljuske? Razvrstano u pdf stvorio bi izvrstan priručnik.

    Živjeli i hvala lijepa!

    1.    hexborg dijo

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

  3.   Kiyov dijo

    vrlo dobar članak, 5+.

    1.    hexborg dijo

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

  4.   sebastian dijo

    Izvrsno! 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' {} \;
    Što se koristi za izvršavanje ove vrste zadatka, ali ne mogu ...
    Zna li netko kako bih to trebao učiniti?
    Zagrliti!
    Seba

    1.    hexborg dijo

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

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

      Također možete koristiti drugi separator u sed. To ne mora biti bar. Sed dopušta 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, da ih Wordpress mijenja za tipografske. 🙂

      Pozdrav.

  5.   sebastian dijo

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

    pronaći. -name "* .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 tisuću čestitki cijeloj grupi.
    Uvijek ih čitam s pošte!
    Zagrljaji
    Seba