Med terminal: Brug af regulære udtryk II: udskiftninger

I mig selv tidligere artikel Jeg har fortalt dig på et grundlæggende niveau, hvordan hver af de mest brugte specialtegn i regulære udtryk fungerer. Med disse regulære udtryk er det muligt at foretage komplekse søgninger i tekstfiler eller i output fra andre kommandoer. I denne artikel skal jeg forklare, hvordan man bruger kommandoen sed til at finde og erstatte tekst på en meget mere kraftfuld måde end blot at ændre en tekst til en anden.

Lidt mere om grep-kommandoen

Før jeg begynder at tale om sed, vil jeg gerne kommentere lidt mere om grep-kommandoen for at fuldføre det, der blev forklaret i den foregående artikel lidt. Alt, hvad jeg vil sige, vil også være relevant for denne. Senere vil vi se forholdet mellem dette og søgninger.

Kombination af regulære udtryk

Mange af de specialtegn, som jeg har talt om i den forrige artikel, kan kombineres, ikke kun med andre tegn, men med hele regelmæssige udtryk. Måden at gøre dette på er at bruge parenteser til at danne en underekspression. Lad os se et eksempel på dette. Lad os starte med at downloade en tekst, som vi kan bruge til test. Det er en liste over sætninger. Til det skal vi bruge følgende kommando:

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

 Dette efterlader dig i det bibliotek, hvor du starter en fil med navnet «sætninger». Du kan åbne det for at se på det og grine lidt. 🙂

Lad os nu antage, at vi vil finde de sætninger, der har nøjagtigt 6 ord. Vanskeligheden er at danne et regulært udtryk, der matcher hvert ord. Et ord er en række af bogstaver, enten store eller små bogstaver, som ville være noget i retning af '[a-zA-Z]+', men du skal også angive, at disse bogstaver skal adskilles af andre tegn end bogstaver, det vil sige, det ville være noget lignende '[a-zA-Z]+[^a-zA-Z]+'. Husk: "^" som det første tegn inden for parenteserne angiver, at vi ønsker at matche med tegn, der ikke er inden for intervallerne, og "+" angiver 1 eller flere tegn.

Vi har allerede et regulært udtryk, der kan matche et ord. For at parre det med 6 skal det gentages 6 gange. Til det brugte vi nøglerne, men de er ubrugelige '[a-zA-Z]+[^a-zA-Z]+{6}', fordi de 6 gentager den sidste del af det regulære udtryk, og hvad vi ønsker er at gentage det hele, så hvad du skal sætte er dette: '([a-zA-Z]+[^a-zA-Z]+){6}'. Med parenteserne danner vi et underekspression, og med seler gentager vi det 6 gange. Nu skal du bare tilføje et "^" foran og et "$" bagtil for at matche hele linjen. Kommandoen er som følger:

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

Og resultatet er lige, hvad vi ønskede:

Det er mere sunget end Macarena. Du er mere færdig end Luis Aguilé. Du har mindre kultur end en sten. Du kender flere sprog end Cañita Brava. Han har flere rynker end Tutan Khamón. Du ved mindre end Rambo om børnepasning.

Bemærk, at vi sætter parameteren -E, fordi vi vil bruge udvidede regulære udtryk til at få "+" til at fungere. Hvis vi brugte de grundlæggende, skulle vi undslippe parenteser og seler.

Tilbagehenvisninger eller tilbagehenvisninger

Hvis du har en stavekontrol installeret, har du sandsynligvis en liste med ord i /usr/share/dict/words. Hvis ikke, kan du installere det i bue med:

sudo pacman -S words

Eller i debian med:

sudo aptitude install dictionaries-common

Hvis du vil, kan du se på filen for at se, hvilke ord den har. Faktisk er det et link til ordfilen på det sprog, hvor din distro er. Du kan have flere ordfiler installeret på samme tid.

Vi skal bruge den fil. Det viser sig, at vi er meget nysgerrige efter at kende alle de syv bogstavs palindromer derude. For dem der ikke ved: En palindrom er et capicúa-ord, det vil sige, det kan læses fra venstre til højre såvel som fra højre mod venstre. Lad os prøve følgende kommando:

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

Det ser lidt underligt ud, ikke? Hvis vi prøver det, afhænger resultatet af sproget i din distro og de ord, der er på din liste, men i mit tilfælde med det spanske sprog er resultatet dette:

anilin anilin rullende

Lad os se, hvordan dette regulære udtryk fungerer.

Bortset fra "^" og "$", som vi allerede ved, hvad det er til, er det første, vi ser til venstre, tre grupper af punkter, der er omgivet af parenteser. Bliv ikke forvirret af bjælkerne foran hver parentes. De skal undslippe parenteserne, fordi vi bruger grundlæggende regulære udtryk, men de har ingen anden betydning. Det vigtige er, at vi beder om tre tegn med prikkerne, men hver af disse prikker er omgivet af parenteser. Dette er for at gemme de tegn, der matcher disse punkter, så de kan henvises til igen fra det regulære udtryk. Dette er en anden brug af parenteser, der kommer til nytte senere ved udskiftning.

Det er her, de tre tal nedenfor kommer med skråstreg foran dem. I dette tilfælde er bjælken vigtig. Det bruges til at angive, at nedenstående nummer er en backreference og henviser til en af ​​de tidligere parenteser. For eksempel: \ 1 henviser til den første parentes, \ 2 til den anden osv.

Det vil sige, med det regulære udtryk, vi har sat, hvad vi leder efter er alle de ord, der starter med fire bogstaver og derefter har et bogstav, der er det samme som det tredje, et andet, der er det samme som det andet og et andet det er det samme som det første. Resultatet er palindromerne på syv bogstaver, der er på ordlisten. Ligesom vi ønskede.

Hvis vi brugte udvidede regulære udtryk, behøver vi ikke slippe for parenteserne, men med udvidede regulære udtryk fungerer backreferences ikke i alle programmer, fordi de ikke er standardiserede. Men med grep fungerer de, så det kan være en anden måde at gøre det samme på. Du kan prøve det, hvis du vil.

Erstatningsudtryk: kommandoen sed

Ud over søgning er en af ​​de bedste anvendelser af regulære udtryk at erstatte komplekse tekster. For at gøre dette er en måde at gøre det på med kommandoen sed. Kraften i kommandoen sed går langt ud over at erstatte tekst, men her skal jeg bruge den til det. Syntaksen, som jeg vil bruge med denne kommando, er følgende:

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

Eller også:

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

Hvor REGEX vil være søgningens regulære udtryk og ERSTAT den nye. Husk, at denne kommando ikke rigtig erstatter noget i den fil, vi angiver, men hvad den gør, er at vise os resultatet af udskiftningen i terminalen, så vær ikke bange for de kommandoer, jeg vil sætte næste. Ingen af ​​dem vil ændre nogen filer på dit system.

Lad os starte med et simpelt eksempel. Vi har alle forskellige konfigurationsfiler i / etc-biblioteket, der normalt har kommentarer, der begynder med "#". Antag, at vi vil se en af ​​disse filer uden kommentarerne. For eksempel vil jeg gøre det med fstab. Du kan prøve med den, du ønsker.

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

Jeg vil ikke lægge resultatet af kommandoen her, fordi det afhænger af, hvad du har i din fstab, men hvis du sammenligner output af kommandoen med indholdet af filen, vil du se, at alle kommentarer er forsvundet.

I denne kommando er søgeudtrykket «#.*", Det er et" # "efterfulgt af et vilkårligt antal tegn, det vil sige kommentarerne. Og erstatningsudtrykket, hvis du ser på de to søjler i træk, vil du se, at der ikke er nogen, så hvad det gør er at erstatte kommentarerne med intet, det vil sige at slette dem. Enklere umuligt.

Nu skal vi gøre det modsatte. Antag, at det, vi ønsker, er at kommentere alle linjerne i filen. Lad os prøve sådan:

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

Du vil se, at i linjerne i kommandoen begynder alle linjerne med et hash-mærke og et tomt mellemrum. Hvad vi har gjort er at erstatte begyndelsen af ​​linjen med «# «. Dette er også et ret simpelt eksempel, hvor teksten, der skal udskiftes, altid er den samme, men nu skal vi komplicere det lidt mere.

Udskiftningernes nåde er, at du i udskiftningsudtrykket kan bruge tilbagehenvisninger som dem, jeg fortalte dig før. Lad os gå tilbage til sætningsfilen, som vi downloadede i begyndelsen af ​​artiklen. Vi vil sætte alle de store bogstaver i parentes inden for parenteser, men vi gør det med en kommando:

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

Det, vi har her, er en tilbagehenvisning i erstatningsudtrykket, der henviser til parenteserne i søgeudtrykket. Parenteserne i erstatningsudtrykket er normale parenteser. I erstatningsudtrykket har de ingen særlig betydning, de er anbragt som de er. Resultatet er, at alle store bogstaver erstattes af det samme bogstav, uanset hvad det er, med parenteser omkring det.

Der er et andet tegn, der også kan bruges i erstatningsudtrykket, det er "&", og det erstattes af al den tekst, der matches med søgeudtrykket. Et eksempel på dette kan være at vedlægge alle sætningerne i filen i anførselstegn. Dette kan opnås med denne kommando:

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

Funktionen af ​​denne kommando ligner meget den forrige, kun nu erstatter vi hele linjen med den samme linje med citater omkring den. Da vi bruger "&", er det ikke nødvendigt at sætte parenteser.

Nogle nyttige kommandoer med regulære udtryk

Her er et par kommandoer, som jeg finder nyttige eller nysgerrige, og som bruger regulære udtryk. Med disse kommandoer er anvendeligheden af ​​regulære udtryk meget bedre end med de eksempler, jeg hidtil har givet, men det syntes mig vigtigt at forklare noget om, hvordan regulære udtryk fungerer for at forstå dem.

  • Vis sektioner af en mandside:

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

Selvfølgelig kan du ændre bash-kommandoen til hvad du vil. Og så fra mand kan du gå direkte til det afsnit, der interesserer dig, ved selvfølgelig at bruge et regelmæssigt udtryk. Tryk på «/» for at starte søgning og skrive «^ALIASES$»For eksempel at gå til afsnittet ALIASES. Jeg tror, ​​det er den første anvendelse, jeg begyndte at gøre med regelmæssige udtryk for et par år siden. Det er næsten umuligt at bevæge sig gennem nogle sider i manualen uden et trick som dette.

  • Vis navnene på alle brugere af maskinen inklusive specielle:

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

  • Vis brugernavne, men kun dem med shell:

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

Det kan virkelig gøres med et enkelt regulært udtryk, men måden at gøre det går ud over, hvad jeg har fortalt dig i disse artikler, så jeg har gjort det ved at kombinere to kommandoer.

  • Indsæt et komma inden de sidste tre cifre af alle numrene i nummerfilen:

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

Det fungerer kun med tal på op til 6 cifre, men kan kaldes mere end én gang for at placere separatorer i de andre grupper på tre cifre.

  •  Uddrag alle e-mail-adresser fra en fil:

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

  • Adskil dag, måned og år for alle datoer, der vises i en fil:

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

  • Find ud af vores lokale IP:

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

Dette kan også gøres med en enkelt sed-kommando, men jeg skal adskille den bedre i en grep og en sed for enkelhedens skyld.

Nogle nyttige adresser

Her er nogle adresser, der kan være nyttige i forbindelse med regulære udtryk:

  • Regular expression-bibliotek: Dette er et bibliotek med almindeligt udtryk, hvor du kan søge efter regulære udtryk relateret til det emne, der interesserer dig. For at søge efter webadresser, ID eller hvad som helst.
  • RegExr: En online-reguleringskontrol. Det giver dig mulighed for at indtaste en tekst og anvende et regulært udtryk på den enten søg eller erstat. Det giver information om det regulære udtryk, og du har et par muligheder for at ændre dets adfærd.
  • Regulære udtryk tester: Det er et tilføjelse til Firefox, der giver dig mulighed for at kontrollere regulære udtryk fra browseren.

Konklusion

For nu er det alt. Regulære udtryk er komplekse, men nyttige. Det tager tid at lære dem, men hvis du er som mig, vil det virke sjovt at lege med dem, og lidt efter lidt vil du mestre dem. Det er en hel verden. Der ville være meget at sige endnu, om dovne kvantificeringsmidler, PERL-stil regex, multiline osv. Og så har hvert program sine karakteristika og dets varianter, så det bedste råd, jeg kan give dig, er at altid se på dokumentationen til det program, du bruger, hver gang du skal skrive et regulært udtryk i et nyt program.

Hej! …HEJ! … VÅGN OP! ... HVAD LOVER I ALLE? 🙂

Fuentes

Nogle af ideerne og eksemplerne til regelmæssige udtryk i denne artikel har jeg taget herfra:


Efterlad din kommentar

Din e-mailadresse vil ikke blive offentliggjort. Obligatoriske felter er markeret med *

*

*

  1. Ansvarlig for dataene: Miguel Ángel Gatón
  2. Formålet med dataene: Control SPAM, management af kommentarer.
  3. Legitimering: Dit samtykke
  4. Kommunikation af dataene: Dataene vil ikke blive kommunikeret til tredjemand, undtagen ved juridisk forpligtelse.
  5. Datalagring: Database hostet af Occentus Networks (EU)
  6. Rettigheder: Du kan til enhver tid begrænse, gendanne og slette dine oplysninger.

  1.   Elav sagde han

    Mesterligt !!!

    1.    hexborg sagde han

      Det er ikke så slemt, men meget tak. Håber folk kan lide det. 🙂

      1.    oscar sagde han

        Jeg kan godt lide det ha!

        1.    hexborg sagde han

          Så må jeg have gjort noget rigtigt. LOL !! 🙂

          Mange tak for din kommentar.

          1.    Blaire pascal sagde han

            Fuck, fortsæt med at skrive mand, fortsæt det.

          2.    hexborg sagde han

            @Blaire Pascal: Kommentarer som din tilskynder det. Mange tak !!

      2.    By sagde han

        Jeg kunne også lide det ... tak 🙂

        1.    hexborg sagde han

          Tak for kommentaren. Jeg håber at skrive et par mere. 🙂

  2.   Marian sagde han

    Dine indlæg er fantastiske, du lærer meget, snarere lærer du at udføre opgaver på en elegant og effektiv måde.

    Har du tænkt på at samle alle dine shell-script-indlæg? Sorteret i en pdf ville gøre en god manual.

    Hej og tak meget!

    1.    hexborg sagde han

      Mange tak!! Det er ikke en dårlig idé. I øjeblikket er der kun to, men jeg vil tænke over det senere. 🙂

  3.   Kiyov sagde han

    meget god artikel, 5+.

    1.    hexborg sagde han

      Tak skal du have. Jeg er glad for du kan lide det. 🙂

  4.   sebastian sagde han

    Fremragende! Jeg har brug for at ændre følgende udtryk, og jeg ved ikke, hvordan man gør det:
    192.168.0.138/Server af 192.168.0.111/data
    Problemet ligger i symbolet "/".
    Jeg bruger kommandoen:
    finde. -navn "* .txt" -exec sed -i 's / TEXT1 / TEXT2 / g' {} \;
    Hvad bruges til at udføre denne type opgave remissivt, men jeg kan ikke ...
    Ved nogen, hvordan jeg skal gøre det?
    Hug!
    Seba

    1.    hexborg sagde han

      Hvad du skal gøre er at undslippe karakteren sådan:

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

      Du kan også bruge en anden separator i sed. Det behøver ikke at være en bar. Sed tillader, at enhver karakter bruges. For eksempel ville dette være klarere:

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

      Og hvis du vil kopiere og indsætte kommandoerne fra denne kommentar, skal du være forsigtig med anførselstegnene, at wordpress ændrer dem til de typografiske. 🙂

      Greetings.

  5.   sebastian sagde han

    Excelente !!!!
    Jeg har ledt efter denne løsning i lang tid.
    Her efterlader jeg den komplette kommando, som jeg har brugt

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

    Fordelen ved denne kommando er, at den ændrer alle .txt-filerne (eller den ønskede udvidelse) rekursivt ... Du skal være meget forsigtig!
    Men det er meget nyttigt !!!

    Tak, tak for alt og tusind tillykke til hele gruppen.
    Jeg læser dem altid fra mailen!
    knus
    Seba