Met Terminal: reguliere expressies gebruiken II: vervangingen

In mezelf artículoenvio anterieure Ik heb je op een basisniveau verteld hoe elk van de meest gebruikte speciale karakters van reguliere expressies werkt. Met deze reguliere expressies is het mogelijk om complexe zoekopdrachten uit te voeren in tekstbestanden of in de uitvoer van andere commando's. In dit artikel ga ik uitleggen hoe je de opdracht sed kunt gebruiken om tekst op een veel krachtigere manier te zoeken en te vervangen dan simpelweg de ene tekst door de andere te veranderen.

Een beetje meer over het grep-commando

Voordat ik over sed begin, zou ik wat meer willen zeggen over het grep-commando om te voltooien wat in het vorige artikel een beetje werd uitgelegd. Alles wat ik ga zeggen, zal ook voor deze relevant zijn. Later zullen we de relatie tussen dit en zoekopdrachten zien.

Combineren van reguliere expressies

Veel van de speciale tekens waarover ik in het vorige artikel heb gesproken, kunnen niet alleen met andere tekens worden gecombineerd, maar ook met hele reguliere expressies. De manier om dit te doen is door haakjes te gebruiken om een ​​subexpressie te vormen. Laten we een voorbeeld hiervan bekijken. Laten we beginnen met het downloaden van een tekst die we kunnen gebruiken om te testen. Het is een lijst met zinnen. Daarvoor gaan we het volgende commando gebruiken:

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

 Dit laat je achter in de directory waar je een bestand start met de naam «phrases». Je kunt het openen om er naar te kijken en een beetje te lachen. 🙂

Laten we nu aannemen dat we de zinnen willen vinden die precies zes woorden hebben. De moeilijkheid zit hem in het vormen van een reguliere expressie die bij elk woord past. Een woord is een reeks letters, hoofdletters of kleine letters, wat er ongeveer zo uitziet '[a-zA-Z]+', maar je moet ook specificeren dat deze letters moeten worden gescheiden door andere tekens dan letters, dat wil zeggen, het zou zoiets zijn als '[a-zA-Z]+[^a-zA-Z]+'. Onthoud: de "^" als het eerste teken tussen de haakjes geeft aan dat we overeen willen komen met tekens die niet in de bereiken staan ​​en de "+" geeft 1 of meer tekens aan.

We hebben al een reguliere expressie die met een woord kan overeenkomen. Om het met 6 te koppelen, moet het 6 keer worden herhaald. Daarvoor hebben we de sleutels gebruikt, maar die hebben geen zin '[a-zA-Z]+[^a-zA-Z]+{6}', omdat de 6 het laatste deel van de reguliere expressie zou herhalen en we willen het allemaal herhalen, dus wat je moet zeggen is dit: '([a-zA-Z]+[^a-zA-Z]+){6}'. Met de haakjes vormen we een onderuitdrukking en met de accolades herhalen we die 6 keer. Nu hoeft u alleen maar een "^" vooraan en een "$" achteraan toe te voegen om overeen te komen met de hele regel. Het commando is als volgt:

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

En het resultaat is precies wat we wilden:

Het wordt meer gezongen dan de Macarena. Je bent meer klaar dan Luis Aguilé. Je hebt minder cultuur dan een steen. U kent meer talen dan Cañita Brava. Hij heeft meer rimpels dan Tutan Khamón. Jij weet minder dan Rambo over kinderopvang.

Merk op dat we de parameter -E plaatsen omdat we uitgebreide reguliere expressies willen gebruiken om de "+" te laten werken. Als we de basis zouden gebruiken, zouden we moeten ontsnappen aan de haakjes en de accolades.

Terugverwijzingen of terugverwijzingen

Als je een spellingcontrole hebt geïnstalleerd, heb je waarschijnlijk een lijst met woorden in /usr/share/dict/words. Zo niet, dan kunt u het in boog installeren met:

sudo pacman -S words

Of in debian met:

sudo aptitude install dictionaries-common

Als je wilt, kun je het bestand bekijken om te zien welke woorden het bevat. Het is eigenlijk een link naar het woordbestand van de taal waarin je distro is. U kunt meerdere Word-bestanden tegelijk installeren.

We gaan dat bestand gebruiken. Het blijkt dat we erg benieuwd zijn naar alle zevenletterige palindromen die er zijn. Voor degenen die het niet weten: een palindroom is een capicúa-woord, dat wil zeggen, het kan zowel van links naar rechts als van rechts naar links worden gelezen. Laten we het volgende commando proberen:

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

Het ziet er een beetje raar uit, toch? Als we het proberen, is het resultaat afhankelijk van de taal van je distro en de woorden die in je lijst staan, maar in mijn geval, met de Spaanse taal, is het resultaat dit:

aniline aniline rollen

Laten we eens kijken hoe deze reguliere expressie werkt.

Afgezien van de "^" en de "$", waarvan we al weten waar het voor is, is het eerste dat we aan de linkerkant zien drie groepen punten tussen haakjes. Laat u niet verwarren door de streepjes voor elk haakje. Ze moeten ontsnappen aan de haakjes omdat we reguliere reguliere expressies gebruiken, maar ze hebben geen andere betekenis. Het belangrijkste is dat we om drie willekeurige tekens met de punten vragen, maar elk van die punten staat tussen haakjes. Dit is om de tekens op te slaan die overeenkomen met die punten, zodat er opnieuw naar kan worden verwezen vanuit de reguliere expressie. Dit is een ander gebruik van haakjes dat later van pas zal komen bij het maken van vervangingen.

Dit is waar de drie onderstaande cijfers komen met de schuine streep ervoor. In dit geval is de balk belangrijk. Het wordt gebruikt om aan te geven dat het onderstaande nummer een terugverwijzing is en verwijst naar een van de vorige haakjes. Bijvoorbeeld: \ 1 verwijst naar het eerste haakje, \ 2 naar het tweede, enzovoort.

Dat wil zeggen, met de reguliere expressie die we hebben ingevoerd, zijn we op zoek naar alle woorden die beginnen met vier letters en dan een letter hebben die hetzelfde is als de derde, een andere die hetzelfde is als de tweede en een andere die hetzelfde is als de eerste. Het resultaat is de zevenletterige palindromen die in de woordenlijst staan. Precies zoals we wilden.

Als we uitgebreide reguliere expressies zouden gebruiken, zouden de haakjes niet moeten worden ontsnapt, maar met uitgebreide reguliere expressies werken terugverwijzingen niet in alle programma's omdat ze niet gestandaardiseerd zijn. Met grep werken ze echter, dus dat kan een andere manier zijn om hetzelfde te doen. Je kunt het proberen als je wilt.

Vervangende uitdrukkingen: het sed-commando

Naast zoeken is een van de beste toepassingen van reguliere expressies het vervangen van complexe teksten. Om dit te doen, is een manier om dit te doen met de opdracht sed. De kracht van het sed-commando gaat veel verder dan het vervangen van tekst, maar hier ga ik het daarvoor gebruiken. De syntaxis die ik met deze opdracht ga gebruiken, is de volgende:

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

Of ook:

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

Waarbij REGEX de reguliere expressie voor zoeken is en REPL de vervangende expressie. Houd er rekening mee dat dit commando niet echt iets in het bestand vervangt dat we aangeven, maar wat het doet is ons het resultaat van de vervanging in de terminal laten zien, dus wees niet bang voor de commando's die ik hierna ga plaatsen. Geen van hen zal bestanden op uw systeem wijzigen.

Laten we beginnen met een eenvoudig voorbeeld. We hebben allemaal verschillende configuratiebestanden in de map / etc die meestal opmerkingen hebben die beginnen met "#". Stel dat we een van deze bestanden willen zien zonder de opmerkingen. Ik ga het bijvoorbeeld doen met de fstab. Je kunt het proberen met degene die je wilt.

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

Ik ga het resultaat van het commando hier niet plaatsen omdat het afhangt van wat je in je fstab hebt, maar als je de uitvoer van het commando vergelijkt met de inhoud van het bestand, zul je zien dat alle commentaren verdwenen zijn.

In dit commando is de zoekuitdrukking «#.*", Dat is een" # "gevolgd door een willekeurig aantal tekens, dat wil zeggen de opmerkingen. En de vervangende uitdrukking, als je naar de twee balken op een rij kijkt, zul je zien dat er geen zijn, dus wat het doet is de opmerkingen vervangen door niets, dat wil zeggen, ze verwijderen. Eenvoudiger onmogelijk.

Nu gaan we het tegenovergestelde doen. Stel dat we alle regels van het bestand willen becommentariëren. Laten we het zo proberen:

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

U zult zien dat in de uitvoer van de opdracht alle regels beginnen met een hekje en een spatie. Wat we hebben gedaan is het begin van de regel vervangen door «# «. Dit is ook een vrij eenvoudig voorbeeld waarbij de te vervangen tekst altijd hetzelfde is, maar nu gaan we het wat ingewikkelder maken.

Het mooie van de vervangingen is dat je in de vervangende uitdrukking terugverwijzingen kunt gebruiken zoals degene die ik je eerder heb verteld. Laten we teruggaan naar het frase-bestand dat we aan het begin van het artikel hebben gedownload. We gaan alle hoofdletters die er zijn tussen haakjes plaatsen, maar we zullen het doen met een commando:

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

Wat we hier hebben is een terugverwijzing in de vervangende uitdrukking die verwijst naar de haakjes in de zoekuitdrukking. De haakjes in de vervangende uitdrukking zijn normale haakjes. In de vervangende uitdrukking hebben ze geen speciale betekenis, ze worden zoals ze zijn. Het resultaat is dat alle hoofdletters worden vervangen door dezelfde letter, wat het ook is, met haakjes eromheen.

Er is nog een ander teken dat ook kan worden gebruikt in de vervangende uitdrukking, het is "&" en het wordt vervangen door alle tekst die overeenkomt met de zoekuitdrukking. Een voorbeeld hiervan is het plaatsen van alle zinnen in het bestand tussen aanhalingstekens. Dit kan worden bereikt met dit commando:

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

De werking van dit commando lijkt erg op het vorige, alleen vervangen we nu de hele regel met dezelfde regel met aanhalingstekens eromheen. Aangezien we "&" gebruiken, is het niet nodig om haakjes te plaatsen.

Enkele handige commando's met reguliere expressies

Hier zijn een paar commando's die ik nuttig of nieuwsgierig vind en die reguliere expressies gebruiken. Met deze commando's is het nut van reguliere expressies veel beter dan met de voorbeelden die ik je tot nu toe heb gegeven, maar het leek me belangrijk om iets uit te leggen over hoe reguliere expressies werken om ze te begrijpen.

  • Secties van een man-pagina weergeven:

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

Natuurlijk kunt u het bash-commando wijzigen in wat u maar wilt. En dan van man, kunt u rechtstreeks naar de sectie gaan die u interesseert, natuurlijk met een reguliere expressie. Druk op «/» om te beginnen met zoeken en schrijf «^ALIASES$»Om bijvoorbeeld naar de sectie ALIASSEN te gaan. Ik denk dat dit het eerste gebruik is dat ik een paar jaar geleden begon te maken van reguliere expressies. Door enkele pagina's van de handleiding bladeren is bijna onmogelijk zonder een truc als deze.

  • Toon de namen van alle gebruikers van de machine inclusief speciale:

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

  • Toon gebruikersnamen, maar alleen die met shell:

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

Het kan echt worden gedaan met een enkele reguliere expressie, maar de manier om het te doen gaat verder dan wat ik je in deze artikelen heb verteld, dus ik heb het gedaan door twee opdrachten te combineren.

  • Plaats een komma voor de laatste drie cijfers van alle cijfers in het cijferbestand:

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

Het werkt alleen met nummers van maximaal 6 cijfers, maar het kan meerdere keren worden gebeld om scheidingstekens in de andere groepen van drie cijfers te plaatsen.

  •  Pak alle e-mailadressen uit een bestand:

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

  • Scheid de dag, maand en jaar van alle datums die in een bestand voorkomen:

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

  • Ontdek ons ​​lokale IP:

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

Dit kan ook worden gedaan met een enkele sed-opdracht, maar ik kan het voor de eenvoud beter scheiden in een grep en een sed.

Enkele handige adressen

Hier zijn enkele adressen die nuttig kunnen zijn met betrekking tot reguliere expressies:

  • Bibliotheek met reguliere expressies: Dit is een bibliotheek met reguliere expressies waarin u kunt zoeken naar reguliere expressies die betrekking hebben op het onderwerp dat u interesseert. Om te zoeken naar webadressen, ID of wat dan ook.
  • RegExr: Een online checker voor reguliere expressies. Hiermee kunt u een tekst invoeren en er een reguliere expressie op toepassen, zoek of vervang. Het geeft informatie over de reguliere expressie en je hebt een paar opties om het gedrag ervan te veranderen.
  • Tester voor reguliere expressies: Het is een add-on voor firefox waarmee u reguliere expressies vanuit de browser kunt controleren.

Conclusie

Voorlopig is dat alles. Reguliere uitdrukkingen zijn complex maar nuttig. Het kost tijd om ze te leren, maar als je net als ik bent, zal het leuk lijken om ermee te spelen en beetje bij beetje zul je ze onder de knie krijgen. Het is een hele wereld. Er zou nog veel te zeggen zijn over luie kwantoren, PERL-stijl regex, multiline, etc. En dan heeft elk programma zijn kenmerken en zijn varianten, dus het beste advies dat ik je kan geven, is om altijd de documentatie te bekijken van het programma dat je gebruikt, elke keer dat je een reguliere expressie in een nieuw programma moet schrijven.

Hallo! …HALLO! … WAKKER WORDEN! … WAT BENT U ALLEMAAL AAN HET SLAPEN? 🙂

Fuentes

Enkele van de ideeën en voorbeelden voor reguliere expressies in dit artikel heb ik hier overgenomen:


Laat je reactie achter

Uw e-mailadres wordt niet gepubliceerd. Verplichte velden zijn gemarkeerd met *

*

*

  1. Verantwoordelijk voor de gegevens: Miguel Ángel Gatón
  2. Doel van de gegevens: Controle SPAM, commentaarbeheer.
  3. Legitimatie: uw toestemming
  4. Mededeling van de gegevens: De gegevens worden niet aan derden meegedeeld, behalve op grond van wettelijke verplichting.
  5. Gegevensopslag: database gehost door Occentus Networks (EU)
  6. Rechten: u kunt uw gegevens op elk moment beperken, herstellen en verwijderen.

  1.   levendig zei

    Meesterlijk!!!

    1.    hexaborg zei

      Het is niet zo erg, maar heel erg bedankt. Ik hoop dat mensen het leuk vinden. 🙂

      1.    oscar zei

        Ik hou van ha!

        1.    hexaborg zei

          Dan heb ik iets goed gedaan. Hahaha!! 🙂

          Heel erg bedankt voor je reactie.

          1.    Blaire pascal zei

            Damn blijf schrijven man ga zo door.

          2.    hexaborg zei

            @Blaire Pascal: Reacties zoals de jouwe moedigen dit aan. 🙂 Heel erg bedankt!!

      2.    Stad zei

        Ik vond het ook leuk ... bedankt 🙂

        1.    hexaborg zei

          Bedankt voor je reactie. Ik hoop er nog een paar te schrijven. 🙂

  2.   Marian zei

    Je berichten zijn fantastisch, je leert veel, liever gezegd, je leert taken elegant en efficiënt uit te voeren.

    Heb je erover nagedacht om al je shellscript-berichten te verzamelen? Gerangschikt in een pdf zouden ze een geweldige handleiding zijn.

    Groetjes en heel erg bedankt!

    1.    hexaborg zei

      Ontzettend bedankt!! Het is geen slecht idee. Op dit moment zijn er slechts twee, maar ik zal er later over nadenken. 🙂

  3.   Kijov zei

    heel goed artikel, 5+.

    1.    hexaborg zei

      Bedankt. Ik ben blij dat je het leuk vind. 🙂

  4.   Sebastian zei

    Uitstekend! Ik moet de volgende uitdrukking wijzigen en ik weet niet hoe ik dat moet doen:
    192.168.0.138/server door 192.168.0.111/data
    Het probleem ligt in het "/" symbool.
    Ik gebruik het commando:
    vinden . -name "*.txt" -exec sed -i 's/TEXT1/TEXT2/g' {} \;
    Wat wordt er gebruikt om dit soort taken remissief uit te voeren, maar ik kan niet...
    Weet iemand hoe ik het moet doen?
    Knuffel!
    Seba

    1.    hexaborg zei

      Wat je moet doen, is als volgt aan het personage ontsnappen:

      vinden . -name "*.txt" -exec sed -i 's/\/Server/\/data/g' {} \;

      U kunt ook een ander scheidingsteken gebruiken in sed. Het hoeft geen bar te zijn. Met Sed kun je elk personage gebruiken. Dit zou bijvoorbeeld duidelijker zijn:

      vinden . -name "*.txt" -exec sed -i 's|/Server|/data|g' {} \;

      En als je de commando's uit deze opmerking gaat kopiëren en plakken, wees dan voorzichtig met de aanhalingstekens, WordPress verandert ze in de typografische. 🙂

      Groeten.

  5.   Sebastian zei

    Uitstekende !!!!
    Ik was al lang op zoek naar deze oplossing.
    Hier laat ik de volledige opdracht achter die ik heb gebruikt

    vinden . -name "*.txt" -exec sed -i 's|192\.168\.0\.238\/Server|192\.168\.0\.111\/data|g' {} \;

    Het voordeel van dit commando is dat het alle .txt-bestanden (of welke extensie je maar wilt) recursief wijzigt... Je moet heel voorzichtig zijn!
    Maar het is erg handig !!!

    Nou, bedankt voor alles en duizend felicitaties aan de hele groep.
    Ik lees ze altijd uit de mail!
    hugs
    Seba