Med terminal: Använda reguljära uttryck II: utbyten

I mig själv tidigare artikel Jag har berättat för dig på grundnivå hur var och en av de mest använda specialtecknen i reguljära uttryck fungerar. Med dessa reguljära uttryck är det möjligt att göra komplexa sökningar i textfiler eller i utdata från andra kommandon. I den här artikeln ska jag förklara hur man använder kommandot sed för att hitta och ersätta text på ett mycket kraftfullare sätt än att bara ändra en text för en annan.

Lite mer om grep-kommandot

Innan jag börjar prata om sed, skulle jag vilja kommentera lite mer om grep-kommandot för att slutföra det som förklarades i föregående artikel lite. Allt jag ska säga kommer också att vara relevant för den här. Senare kommer vi att se förhållandet mellan detta och sökningar.

Kombinera reguljära uttryck

Många av de specialtecken som jag har pratat om i föregående artikel kan kombineras, inte bara med andra karaktärer, utan med hela regelbundna uttryck. Sättet att göra detta är att använda parenteser för att bilda ett subuttryck. Låt oss se ett exempel på detta. Låt oss börja med att ladda ner en text som vi kan använda för testning. Det är en lista med fraser. För det ska vi använda följande kommando:

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

 Detta lämnar dig i katalogen där du startar en fil med namnet «fraser». Du kan öppna det för att titta och skratta lite. 🙂

Låt oss nu anta att vi vill hitta fraser som har exakt sex ord. Svårigheten är att skapa ett regelbundet uttryck som matchar varje ord. Ett ord är en sekvens av bokstäver, antingen versaler eller små bokstäver, vilket skulle vara ungefär som '[a-zA-Z]+', men du måste också ange att dessa bokstäver måste separeras med andra tecken än bokstäver, det vill säga det skulle vara ungefär som '[a-zA-Z]+[^a-zA-Z]+'. Kom ihåg: "^" som det första tecknet i parenteserna indikerar att vi vill matcha med tecken som inte finns i intervallen och "+" anger 1 eller flera tecken.

Vi har redan ett reguljärt uttryck som kan matcha ett ord. För att para ihop det med 6 måste det upprepas 6 gånger. För det använde vi nycklarna, men det är värdelöst att sätta '[a-zA-Z]+[^a-zA-Z]+{6}', eftersom 6 skulle upprepa den sista delen av det reguljära uttrycket och vad vi vill är att upprepa allt, så vad du måste sätta är detta: '([a-zA-Z]+[^a-zA-Z]+){6}'. Med parenteserna bildar vi ett subuttryck och med hängslen upprepar vi det 6 gånger. Nu behöver du bara lägga till ett "^" framför och ett "$" på baksidan för att matcha hela raden. Kommandot är som följer:

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

Och resultatet är precis vad vi ville ha:

Det är mer sjungit än Macarena. Du är mer färdig än Luis Aguilé. Du har mindre kultur än en sten. Du kan fler språk än Cañita Brava. Han har fler rynkor än Tutan Khamón. Du vet mindre än Rambo om barnomsorg.

Lägg märke till att vi sätter parametern -E eftersom vi vill använda utökade reguljära uttryck för att få "+" att fungera. Om vi ​​använde de grundläggande skulle vi behöva fly från parenteserna och hängslen.

Tillbaka referenser eller bakreferenser

Om du har en stavningskontroll installerad kommer du antagligen att ha en lista med ord i /usr/share/dict/words. Om inte, kan du installera den i arch med:

sudo pacman -S words

Eller i debian med:

sudo aptitude install dictionaries-common

Om du vill kan du titta på filen för att se vilka ord den har. Egentligen är det en länk till ordfilen för det språk som din distro är på. Du kan ha flera ordfiler installerade samtidigt.

Vi ska använda den filen. Det visar sig att vi är väldigt nyfikna på att känna till alla de sju bokstäver palindromerna där ute. För dem som inte vet: En palindrom är ett capicúa-ord, det vill säga det kan läsas från vänster till höger såväl som från höger till vänster. Låt oss prova följande kommando:

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

Det ser lite konstigt ut, eller hur? Om vi ​​provar det beror resultatet på språket i din distro och de ord som finns i din lista, men i mitt fall, med det spanska språket, är resultatet detta:

anilin anilin rullande

Låt oss se hur det här reguljära uttrycket fungerar.

Bortsett från "^" och "$", som vi redan vet vad det är för, är det första vi ser till vänster tre grupper av prickar som är inneslutna inom parentes. Var inte förvirrad av staplarna framför varje parentes. De ska undkomma inom parentes eftersom vi använder grundläggande reguljära uttryck, men de har ingen annan betydelse. Det viktiga är att vi ber om tre tecken med punkterna, men var och en av dessa punkter är inom parentes. Detta är för att spara de tecken som matchar dessa punkter så att de kan hänvisas igen från det reguljära uttrycket. Detta är en annan användning av parenteser som kommer att vara till nytta senare när du gör utbyten.

Det är här de tre siffrorna nedan kommer med snedstrecket framför dem. I det här fallet är stapeln viktig. Den används för att indikera att numret nedan är en bakreferens och hänvisar till en av de tidigare parenteserna. Till exempel: \ 1 hänvisar till den första parentesen, \ 2 till den andra, och så vidare.

Det vill säga, med det reguljära uttryck som vi har satt, är det vi letar efter alla ord som börjar med fyra bokstäver och sedan har en bokstav som är densamma som den tredje, en annan som är densamma som den andra och en annan det är samma som det första. Resultatet är palindromerna med sju bokstäver som finns i ordlistan. Precis som vi ville.

Om vi ​​använde utökade reguljära uttryck skulle vi inte behöva fly från parenteserna, men med utökade reguljära uttryck fungerar inte backreferenser i alla program eftersom de inte är standardiserade. Men med grep fungerar de, så det kan vara ett annat sätt att göra detsamma. Du kan prova det om du vill.

Ersättningsuttryck: kommandot sed

Förutom att söka är en av de bästa användningarna av reguljära uttryck att ersätta komplexa texter. För att göra detta är ett sätt att göra det med kommandot sed. Kraften i kommandot sed går långt utöver att ersätta text, men här ska jag använda den för det. Syntaxen som jag ska använda med det här kommandot är följande:

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

Eller också:

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

Där REGEX kommer att vara sökningens reguljära uttryck och REPL ersätta den. Tänk på att det här kommandot egentligen inte ersätter någonting i filen som vi anger, men vad det gör är att visa oss resultatet av utbytet i terminalen, så var inte rädd för de kommandon som jag ska lägga nästa. Ingen av dem kommer att ändra några filer på ditt system.

Låt oss börja med ett enkelt exempel. Vi har alla olika konfigurationsfiler i / etc-katalogen som vanligtvis har kommentarer som börjar med "#". Antag att vi vill se en av dessa filer utan kommentarer. Till exempel ska jag göra det med fstab. Du kan prova med den du vill ha.

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

Jag kommer inte att lägga här resultatet av kommandot eftersom det beror på vad du har i din fstab, men om du jämför kommandot med kommandot med innehållet i filen ser du att alla kommentarer har försvunnit.

I detta kommando är sökuttrycket «#.*", Det är ett" # "följt av valfritt antal tecken, det vill säga kommentarerna. Och ersättningsuttrycket, om du tittar på de två staplarna i rad, kommer du att se att det inte finns några, så vad det gör är att ersätta kommentarerna med ingenting, det vill säga ta bort dem. Enklare omöjligt.

Nu ska vi göra det motsatta. Antag att det vi vill ha är att kommentera alla rader i filen. Låt oss försöka så här:

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

Du kommer att se att, i utgången av kommandot, börjar alla rader med ett hashmärke och ett tomt utrymme. Vad vi har gjort är att ersätta början på raden med «# «. Detta är också ett ganska enkelt exempel där texten som ska ersättas alltid är densamma, men nu kommer vi att komplicera det lite mer.

Utbytets nåd är att i ersättningsuttrycket kan du använda bakreferenser som de jag sa tidigare. Låt oss gå tillbaka till frasfilen som vi laddade ner i början av artikeln. Vi kommer att sätta inom parentes alla stora bokstäver som finns, men vi kommer att göra det med ett kommando:

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

Vad vi har här är en bakreferens i ersättningsuttrycket som hänvisar till parenteserna i sökuttrycket. Parenteserna i ersättningsuttrycket är normala parenteser. I ersättningsuttrycket har de ingen speciell betydelse, de sätts som de är. Resultatet är att alla stora bokstäver ersätts av samma bokstav, oavsett vilken det är, med parenteser runt den.

Det finns ett annat tecken som också kan användas i ersättningsuttrycket, det är "&" och det ersätts av all text som matchas av sökuttrycket. Ett exempel på detta kan vara att sätta alla fraser i filen i citat. Detta kan uppnås med detta kommando:

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

Funktionen för det här kommandot liknar den tidigare, bara nu ersätter vi hela raden med samma rad med citat runt. Eftersom vi använder "&" är det inte nödvändigt att sätta inom parentes.

Några användbara kommandon med reguljära uttryck

Här är några kommandon som jag tycker är användbara eller nyfikna och som använder reguljära uttryck. Med dessa kommandon är användningen av reguljära uttryck mycket bättre än med de exempel som jag hittills har gett dig, men det verkade viktigt att förklara något om hur reguljära uttryck fungerar för att förstå dem.

  • Visa avsnitt på en mansida:

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

Naturligtvis kan du ändra bash-kommandot till vad du vill. Och sedan från människa kan du gå direkt till det avsnitt som intresserar dig med naturligtvis ett vanligt uttryck. Tryck på «/» för att börja söka och skriva «^ALIASES$»För att gå till avsnittet ALIASES, till exempel. Jag tror att detta är den första användningen av reguljära uttryck för några år sedan. Att bläddra igenom vissa sidor i manualen är nästan omöjligt utan ett trick som detta.

  • Visa namnen på alla användare av maskinen inklusive speciella:

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

  • Visa användarnamn, men bara de med skal:

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

Det kan verkligen göras med ett enda reguljärt uttryck, men sättet att göra det går utöver vad jag har sagt i dessa artiklar, så jag har gjort det genom att kombinera två kommandon.

  • Infoga ett komma före de tre sista siffrorna i alla siffror i siffran:

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

Det fungerar bara med siffror upp till 6 siffror, men det kan kallas mer än en gång för att placera separatorer i de andra grupperna med tre siffror.

  •  Extrahera alla e-postadresser från en fil:

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

  • Separera dag, månad och år för alla datum som visas 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

  • Ta reda på vår lokala IP:

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

Detta kan också göras med ett enda sed-kommando, men jag borde separera det i en grep och en sed för enkelhetens skull.

Några användbara adresser

Här är några adresser som kan vara användbara i samband med reguljära uttryck:

  • Bibliotek för vanligt uttryck: Detta är ett reguljärt uttrycksbibliotek där du kan söka efter reguljära uttryck relaterade till ämnet som intresserar dig. För att söka efter webbadresser, ID eller vad som helst.
  • RegExr: En online-reguljär expressionskontroll. Det låter dig skriva in en text och tillämpa ett reguljärt uttryck på den antingen söka eller ersätta. Det ger information om det reguljära uttrycket och du har några alternativ för att ändra dess beteende.
  • Testare för reguljära uttryck: Det är ett tillägg för Firefox som låter dig kontrollera reguljära uttryck från webbläsaren.

Slutsats

För nu är det allt. Regulära uttryck är komplexa men användbara. Det tar tid att lära sig dem, men om du är som jag kommer det att vara roligt att leka med dem och lite efter lite kommer du att bemästra dem. Det är en hel värld. Det skulle vara mycket att säga ännu, om lata kvantifierare, PERL-stil regex, multiline, etc. Och då har varje program sina egenskaper och dess varianter, så det bästa rådet jag kan ge dig är att alltid titta på dokumentationen för programmet som du använder varje gång du måste skriva ett reguljärt uttryck i ett nytt program.

Hallå! …HALLÅ! … VAKNA! ... VAD GÖR DU ALLA SOVA? 🙂

Källor

Några av idéerna och exemplen för regelbundna uttryck i den här artikeln har jag tagit härifrån:


Lämna din kommentar

Din e-postadress kommer inte att publiceras. Obligatoriska fält är markerade med *

*

*

  1. Ansvarig för uppgifterna: Miguel Ángel Gatón
  2. Syftet med uppgifterna: Kontrollera skräppost, kommentarhantering.
  3. Legitimering: Ditt samtycke
  4. Kommunikation av uppgifterna: Uppgifterna kommer inte att kommuniceras till tredje part förutom enligt laglig skyldighet.
  5. Datalagring: databas värd för Occentus Networks (EU)
  6. Rättigheter: När som helst kan du begränsa, återställa och radera din information.

  1.   livlig sade

    Mästerlig!!!

    1.    hexborg sade

      Det är inte så illa, men tack så mycket. Hoppas att folk gillar det. 🙂

      1.    oscar sade

        Jag gillar det ha!

        1.    hexborg sade

          Då måste jag ha gjort något rätt. LOL!! 🙂

          Tack så mycket för din kommentar.

          1.    Blaire pascal sade

            Fan fortsätt skriva man, fortsätt det.

          2.    hexborg sade

            @Blaire Pascal: Kommentarer som din uppmuntrar det. Tack så mycket !!

      2.    Stad sade

        Jag gillade det också ... tack 🙂

        1.    hexborg sade

          Tack för din kommentar. Jag hoppas kunna skriva några fler. 🙂

  2.   Marian sade

    Dina inlägg är fantastiska, du lär dig mycket, snarare lär du dig att utföra uppgifter på ett elegant och effektivt sätt.

    Har du funderat på att samla in alla dina shell-skriptinlägg? Sorterat i en pdf skulle göra en bra manual.

    Skål och tack så mycket!

    1.    hexborg sade

      Tack så mycket!! Det är ingen dålig idé. För närvarande finns det bara två, men jag kommer att tänka på det senare. 🙂

  3.   Kiyov sade

    mycket bra artikel, 5+.

    1.    hexborg sade

      Tack. Jag är glad att du gillar det. 🙂

  4.   Sebastian sade

    Excellent! Jag måste ändra följande uttryck och jag vet inte hur man gör det:
    192.168.0.138/Server av 192.168.0.111/data
    Problemet ligger i symbolen "/".
    Jag använder kommandot:
    hitta. -namn "* .txt" -exec sed -i's / TEXT1 / TEXT2 / g '{} \;
    Vad används för att utföra denna typ av uppgift remissivt, men jag kan inte ...
    Vet någon hur jag ska göra det?
    Kram!
    Seba

    1.    hexborg sade

      Vad du måste göra är att fly från karaktären så här:

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

      Du kan också använda en annan separator i sed. Det behöver inte vara en bar. Sed tillåter att alla karaktärer används. Till exempel skulle detta vara tydligare:

      hitta. -namn "* .txt" -exec sed -is | / Server | / data | g '{} \;

      Och om du ska kopiera och klistra in kommandona från den här kommentaren, var försiktig med citaten, att wordpress ändrar dem för de typografiska. 🙂

      Hälsningar.

  5.   Sebastian sade

    Excellent!!!!
    Jag har letat efter den här lösningen länge.
    Här lämnar jag det fullständiga kommandot som jag har använt

    hitta. -namn "* .txt" -exec sed -is | 192 \ .168 \ .0 \ .238 \ / Server | 192 \ .168 \ .0 \ .111 \ / data | g '{} \;

    Fördelen med det här kommandot är att det ändrar alla .txt-filer (eller tillägget du vill ha) rekursivt ... Du måste vara mycket försiktig!
    Men det är mycket användbart !!!

    Tack för allt och tusen gratulationer till hela gruppen.
    Jag läser dem alltid från posten!
    Kramar
    Seba