S terminálom: Používanie regulárnych výrazov II: Náhrady

V sebe predchádzajúci článok Na základnej úrovni som vám povedal, ako fungujú jednotlivé najpoužívanejšie špeciálne znaky regulárnych výrazov. Pomocou týchto regulárnych výrazov je možné vykonať komplexné vyhľadávanie v textových súboroch alebo na výstupe z iných príkazov. V tomto článku vysvetlím, ako používať príkaz sed na nájdenie a nahradenie textu oveľa výkonnejším spôsobom, ako je jednoduchá zmena jedného textu za iný.

Trochu viac o príkaze grep

Predtým, ako začnem hovoriť o sede, rád by som sa ešte trochu vyjadril k príkazu grep, aby som trochu dokončil to, čo bolo vysvetlené v predchádzajúcom článku. Všetko, čo poviem, bude relevantné aj pre tento. Neskôr uvidíme vzťah medzi týmto a vyhľadávaniami.

Kombinácia regulárnych výrazov

Mnoho špeciálnych znakov, o ktorých som hovoril v predchádzajúcom článku, je možné kombinovať nielen s inými znakmi, ale s celými regulárnymi výrazmi. Spôsob, ako to urobiť, je použiť zátvorky na vytvorenie podvýrazu. Pozrime sa na príklad. Začnime stiahnutím textu, ktorý môžeme použiť na testovanie. Je to zoznam fráz. Na to použijeme nasledujúci príkaz:

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

 Toto vás ponechá v adresári, kde spustíte súbor s názvom «frázy». Môžete ho otvoriť, pozrieť sa a trochu sa zasmiať. 🙂

Teraz predpokladajme, že chceme nájsť frázy, ktoré majú presne 6 slov. Ťažkosti sú vo formovaní regulárneho výrazu, ktorý zodpovedá každému slovu. Slovo je sled písmen, veľké alebo malé, ktoré by mohli byť podobné '[a-zA-Z]+', ale tiež musíte určiť, že tieto písmená musia byť oddelené inými znakmi ako písmenami, to znamená, že by to malo byť niečo ako '[a-zA-Z]+[^a-zA-Z]+'. Pamätajte: znak „^“ ako prvý znak v zátvorkách naznačuje, že sa chceme zhodovať so znakmi, ktoré nie sú v rozsahu, a znak „+“ označuje 1 alebo viac znakov.

Už máme regulárny výraz, ktorý sa môže zhodovať so slovom. Ak ho chcete spárovať so 6, bude sa musieť opakovať 6-krát. Na to sme použili kľúče, ale je zbytočné ich dávať '[a-zA-Z]+[^a-zA-Z]+{6}', pretože 6 by zopakovala poslednú časť regulárneho výrazu a čo chceme, je opakovať to všetko, takže musíme dať toto: '([a-zA-Z]+[^a-zA-Z]+){6}'. So zátvorkami vytvoríme subexpresiu a so zloženými zátvorkami to zopakujeme 6 krát. Teraz stačí pridať pred seba znak „^“ a vzadu znak „$“, aby sa zhodoval s celým riadkom. Príkaz je nasledovný:

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

A výsledok je to, čo sme chceli:

Je to spievanejšie ako Macarena. Ste hotovejší ako Luis Aguilé. Máte menej kultúry ako kameň. Viete viac jazykov ako Cañita Brava. Má viac vrások ako Tutan Khamón. O starostlivosti o deti viete menej ako Rambo.

Všimnite si, že sme vložili parameter -E, pretože chceme, aby funkčnosť znaku „+“ fungovala pomocou rozšírených regulárnych výrazov. Keby sme použili tie základné, museli by sme uniknúť zátvorkám a zloženým zátvorkám.

Spätné referencie alebo spätné referencie

Ak máte nainštalovanú kontrolu pravopisu, pravdepodobne tu budete mať zoznam slov /usr/share/dict/words. Ak nie, môžete ho nainštalovať do archu pomocou:

sudo pacman -S words

Alebo v debiane s:

sudo aptitude install dictionaries-common

Ak chcete, môžete sa pozrieť do súboru a zistiť, aké slová majú. V skutočnosti ide o odkaz na súbor slova v jazyku, v ktorom je vaša distribúcia. Môžete mať nainštalovaných niekoľko slovných súborov súčasne.

Ten súbor použijeme. Ukazuje sa, že sme veľmi zvedaví, aby sme poznali všetkých sedem palindrómov so siedmimi písmenami. Pre tých, ktorí nevedia: Palindróm je slovo capicúa, to znamená, že sa dá čítať zľava doprava aj sprava doľava. Vyskúšajme nasledujúci príkaz:

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

Vyzerá to trochu zvláštne, že? Ak to skúsime, výsledok bude závisieť od jazyka vašej distribúcie a slov, ktoré sa nachádzajú vo vašom zozname, ale v mojom prípade so španielskym jazykom bude výsledok taký:

anilín anilín valcovanie

Pozrime sa, ako tento regulárny výraz funguje.

Okrem znakov „^“ a „$“, ktoré už vieme, na čo slúžia, sú prvé veci, ktoré vidíme vľavo, tri skupiny bodov uzavreté v zátvorkách. Nenechajte sa zmiasť mrežami pred každou zátvorkou. Majú uniknúť zo zátvoriek, pretože používame základné regulárne výrazy, ale nemajú žiadny iný význam. Dôležité je, že požadujeme ľubovoľné tri znaky s bodkami, ale každá z nich je uvedená v zátvorkách. To slúži na uloženie znakov, ktoré sa zhodujú s týmito bodmi, aby na ne bolo možné znova odkazovať z regulárneho výrazu. Toto je ďalšie použitie zátvoriek, ktoré sa vám neskôr budú hodiť pri vytváraní náhrady.

To je miesto, kde tri nižšie uvedené čísla prichádzajú s lomítkom pred nimi. V tomto prípade je dôležitá lišta. Používa sa na označenie, že nižšie uvedené číslo je spätnou referenciou a odkazuje na jednu z predchádzajúcich zátvoriek. Napríklad: \ 1 odkazuje na prvú zátvorku, \ 2 na druhú atď.

To znamená, že s regulárnym výrazom, ktorý sme vložili, hľadáme všetky slová, ktoré sa začínajú ľubovoľnými štyrmi písmenami a potom majú písmeno, ktoré je rovnaké ako tretie, ďalšie, ktoré je rovnaké ako druhé a ďalšie, ktoré je rovnaké ako najprv. Výsledkom sú sedempísmenové palindrómy, ktoré sa nachádzajú v zozname slov. Presne tak, ako sme chceli.

Ak by sme používali rozšírené regulárne výrazy, zátvorky by nemuseli uniknúť, ale s rozšírenými regulárnymi výrazmi spätné odkazy nefungujú vo všetkých programoch, pretože nie sú štandardizované. S grepom však fungujú, takže to môže byť ďalší spôsob, ako urobiť to isté. Ak chcete, môžete to vyskúšať.

Náhradné výrazy: príkaz sed

Okrem vyhľadávania je jedným z najlepších spôsobov použitia regulárnych výrazov nahradenie zložitých textov. Jedným zo spôsobov, ako to urobiť, je príkaz sed. Sila príkazu sed ide ďaleko za nahradenie textu, ale tu ho na to použijem. Syntax, ktorú použijem s týmto príkazom, je nasledovná:

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

Alebo tiež:

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

Kde REGEX bude regulárny výraz vyhľadávania a REPL náhradný. Majte na pamäti, že tento príkaz skutočne nenahradí nič v súbore, ktorý označíme, ale to, čo urobí, je, že nám ukáže výsledok výmeny v termináli, takže sa nemusíte báť príkazmi, ktoré uvediem ďalej. Žiadny z nich nebude upravovať žiadne súbory vo vašom systéme.

Začnime jednoduchým príkladom. Všetci máme rôzne konfiguračné súbory v adresári / etc, ktoré majú zvyčajne komentáre začínajúce znakom „#“. Predpokladajme, že chceme vidieť jeden z týchto súborov bez komentárov. Napríklad to urobím pomocou fstab. Môžete skúsiť s tým, ktorý chcete.

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

Nebudem sem dávať výsledok príkazu, pretože záleží na tom, čo máte vo svojom fstab, ale ak porovnáte výstup príkazu s obsahom súboru, uvidíte, že všetky komentáre zmizli.

V tomto príkaze je hľadaný výraz «#.*„, To je„ # “, za ktorým nasleduje ľubovoľný počet znakov, to znamená komentáre. A náhradný výraz, keď sa pozriete na dva pruhy za sebou, uvidíte, že žiadne nie sú, takže to, čo robí, je nahradenie komentárov ničím, to znamená ich odstránenie. Jednoduchšie nemožné.

Teraz urobíme pravý opak. Predpokladajme, že chceme komentovať všetky riadky súboru. Skúsme to takto:

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

Uvidíte, že na výstupe príkazu sa všetky riadky začínajú znakom hash a prázdnym miestom. To, čo sme urobili, je nahradiť začiatok riadka znakom «# «. Toto je tiež celkom jednoduchý príklad, keď je text, ktorý sa má nahradiť, vždy rovnaký, teraz to však ešte trochu skomplikujeme.

Milosť nahradenia spočíva v tom, že v náhradnom výraze môžete použiť spätné referencie, aké som vám povedal predtým. Vráťme sa k súboru fráz, ktorý sme si stiahli na začiatku článku. Dáme do zátvoriek všetky veľké písmená, ktoré existujú, ale urobíme to príkazom:

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

Máme tu spätnú referenciu v náhradnom výraze, ktorý odkazuje na zátvorky vo vyhľadávacom výraze. Zátvorky v náhradnom výraze sú normálne zátvorky. V náhradnom výraze nemajú žiadny zvláštny význam, sú uvedené tak, ako sú. Výsledkom je, že všetky veľké písmená sú nahradené rovnakým písmenom, bez ohľadu na to, aké je, so zátvorkami.

V náhradnom výraze je možné použiť aj ďalší znak, je to „&“ a je nahradený celým textom, ktorý sa zhoduje s hľadaným výrazom. Príkladom toho môže byť uvedenie všetkých fráz do súboru v úvodzovkách. Toto je možné dosiahnuť pomocou tohto príkazu:

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

Fungovanie tohto príkazu je veľmi podobné predchádzajúcemu, len teraz nahradíme celý riadok rovnakým riadkom s úvodzovkami. Pretože používame „&“, nie je potrebné uvádzať zátvorky.

Niektoré užitočné príkazy s regulárnymi výrazmi

Tu uvádzam niekoľko príkazov, ktoré považujem za užitočné alebo zvedavé a ktoré používajú regulárne výrazy. S týmito príkazmi je užitočnosť regulárnych výrazov oveľa lepšia ako s príkladmi, ktoré som vám doteraz uviedol, ale zdalo sa mi dôležité vysvetliť niečo o tom, ako regulárne výrazy fungujú, aby som im porozumel.

  • Zobraziť sekcie manuálovej stránky:

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

Príkaz bash môžete samozrejme zmeniť na čo chcete. A potom od človeka môžete prejsť priamo do sekcie, ktorá vás zaujíma, samozrejme pomocou regulárneho výrazu. Stlačením «/» zahájite vyhľadávanie a napíšete «^ALIASES$»Prejdete napríklad do sekcie ALIASES. Myslím, že toto je prvé použitie regulárnych výrazov, ktoré som začal používať pred niekoľkými rokmi. Pohyb po niektorých stránkach manuálu je bez takého triku takmer nemožný.

  • Zobraziť mená všetkých používateľov stroja vrátane tých zvláštnych:

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

  • Zobraziť používateľské mená, ale iba tie, ktoré majú shell:

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

Naozaj sa to dá urobiť pomocou jedného regulárneho výrazu, ale spôsob, ako to urobiť, ide nad rámec toho, čo som vám povedal v týchto článkoch, takže som to urobil kombináciou dvoch príkazov.

  • Pred posledné tri číslice všetkých čísel v číselnom súbore vložte čiarku:

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

Funguje iba s číslami do 6 číslic, ale je možné ich zavolať viackrát, aby sa oddeľovače umiestnili do ďalších trojmiestnych skupín.

  •  Extrahujte všetky e-mailové adresy zo súboru:

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

  • Oddeľte deň, mesiac a rok od všetkých dátumov, ktoré sa nachádzajú v súbore:

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

  • Zistite našu miestnu IP adresu:

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

To sa dá urobiť aj jediným príkazom sed, ale pre jednoduchosť to lepšie rozdelím na grep a sed.

Niekoľko užitočných adries

Tu je niekoľko adries, ktoré môžu byť užitočné v súvislosti s regulárnymi výrazmi:

  • Knižnica regulárnych výrazov: Toto je knižnica regulárnych výrazov, v ktorej môžete vyhľadávať regulárne výrazy súvisiace s témou, ktorá vás zaujíma. Ak chcete vyhľadať webové adresy, ID alebo čokoľvek iné.
  • RegExr: Online kontrola regulárneho výrazu. Umožňuje vám zadať text a použiť na neho regulárny výraz, a to buď vyhľadaním alebo nahradením. Poskytuje informácie o regulárnom výraze a máte niekoľko možností, ako zmeniť jeho správanie.
  • Tester regulárnych výrazov: Je to doplnok pre firefox, ktorý vám umožňuje kontrolovať regulárne výrazy z prehliadača.

Záver

To je zatiaľ všetko. Regulárne výrazy sú zložité, ale užitočné. Naučiť sa ich vyžaduje čas, ale ak ste ako ja, hra s nimi sa vám bude zdať zábavná a postupne ich budete ovládať. Je to celý svet. Zatiaľ by bolo veľa čo povedať o lenivých kvantifikátoroch, regulárnom výraze v štýle PERL, viacriadkových atď. A potom každý program má svoje vlastnosti a jeho varianty, takže najlepšou radou, ktorú vám môžem dať, je pozrieť si vždy dokumentáciu k programu, ktorú používate, zakaždým, keď musíte do nového programu napísať regulárny výraz.

Hej! ... Ahoj! … ZOBUDIŤ SA! … ČO VŠETCI SPÍTE? 🙂

Fuentes

Niektoré z nápadov a príkladov pre regulárne výrazy v tomto článku, ktoré som si vzal odtiaľto:


Zanechajte svoj komentár

Vaša e-mailová adresa nebude zverejnená. Povinné položky sú označené *

*

*

  1. Zodpovedný za údaje: Miguel Ángel Gatón
  2. Účel údajov: Kontrolný SPAM, správa komentárov.
  3. Legitimácia: Váš súhlas
  4. Oznamovanie údajov: Údaje nebudú poskytnuté tretím stranám, iba ak to vyplýva zo zákona.
  5. Ukladanie dát: Databáza hostená spoločnosťou Occentus Networks (EU)
  6. Práva: Svoje údaje môžete kedykoľvek obmedziť, obnoviť a vymazať.

  1.   živý dijo

    Majstrovsky !!!

    1.    hexborg dijo

      Nie je to také zlé, ale veľmi pekne ďakujem. Dúfam, že sa to ľuďom páči. 🙂

      1.    Oskar dijo

        Páči sa mi to ha!

        1.    hexborg dijo

          Potom som musel urobiť niečo dobre. LOL !! 🙂

          Ďakujem pekne za komentár.

          1.    Blaire pascal dijo

            Kurva pokračuj v písaní človeče, len tak ďalej.

          2.    hexborg dijo

            @Blaire Pascal: Takéto komentáre vás povzbudzujú. 🙂 dakujem pekne !!

      2.    Mesto dijo

        Tiež sa mi páčilo ... ďakujem 🙂

        1.    hexborg dijo

          Ďakujem za komentár. Dúfam, že ešte pár napíšem. 🙂

  2.   Marian dijo

    Vaše príspevky sú fantastické, veľa sa toho dozviete, skôr sa naučíte vykonávať úlohy elegantným a efektívnym spôsobom.

    Už ste premýšľali o zhromaždení všetkých svojich príspevkov do shellového skriptu? Ak by ste ich vytriedili do formátu PDF, bol by z nich vynikajúci manuál.

    Na zdravie a veľmi pekne ďakujem!

    1.    hexborg dijo

      Mnohokrat dakujem!! Nie je to zlý nápad. Momentálne sú iba dvaja, ale nad tým budem uvažovať neskôr. 🙂

  3.   Kijov dijo

    veľmi dobrý článok, 5+.

    1.    hexborg dijo

      Ďakujem. Som rád, že sa vám to páči. 🙂

  4.   Sebastian dijo

    Vynikajúci! Potrebujem zmeniť nasledujúci výraz a neviem, ako na to:
    192.168.0.138/Server do 192.168.0.111/data
    Problém spočíva v symbole „/“.
    Používam príkaz:
    Nájsť. -name "* .txt" -exec sed -i 's / TEXT1 / TEXT2 / g' {} \;
    Čo sa používa na vykonávanie tohto typu úlohy remisívne, ale nemôžem ...
    Vie niekto ako by som to mal urobiť?
    Objať!
    Seba

    1.    hexborg dijo

      Musíte uniknúť z postavy takto:

      Nájsť. -name "* .txt" -exec sed -i 's / \ / Server / \ / data / g' {} \;

      Môžete tiež použiť iný oddeľovač v sed. Nemusí to byť bar. Sed umožňuje použitie ľubovoľných znakov. Bolo by to napríklad jasnejšie:

      Nájsť. -name "* .txt" -exec sed -i | / Server | / data | g '{} \;

      A ak budete kopírovať a vkladať príkazy z tohto komentára, buďte opatrní pri úvodzovkách, ktoré WordPress zmení za tie typografické. 🙂

      Zdravím.

  5.   Sebastian dijo

    Výborne !!!!
    Toto riešenie som hľadal dlho.
    Tu ponechávam celý príkaz, ktorý som použil

    Nájsť. -name "* .txt" -exec sed -i 's | 192 \ .168 \ .0 \ .238 \ / server | 192 \ .168 \ .0 \ .111 \ / data | g' {} \;

    Výhodou tohto príkazu je, že rekurzívne mení všetky súbory .txt (alebo požadovanú príponu) ... Musíte byť veľmi opatrní!
    Ale je to veľmi užitočné !!!

    No vďaka za všetko a tisíc gratulácií celej skupine.
    Vždy som ich čítal z pošty!
    Objatia
    Seba