Utbildningsprogram om GREP och reguljära uttryck. Använda reguljära uttryck (regex) i Linux Regular expression table grep

Verktyget grep är ett mycket kraftfullt sök- och filterverktyg. textinformation. Den här artikeln visar flera exempel på dess användning som gör att du kan uppskatta dess kapacitet.
Den huvudsakliga användningen av grep är att söka efter ord eller fraser i filer och utdataströmmar. Du kan söka genom att skriva en fråga och sökområdet (filen) på kommandoraden.
Till exempel, för att hitta strängen "needle" i filen hystack.txt, använd följande kommando:

$ grep needle haystack.txt

Som ett resultat kommer grep att visa alla förekomster av nål som den stöter på i innehållet i filen haystack.txt. Det är viktigt att notera att i det här fallet letar grep efter en uppsättning tecken, inte ett ord. Till exempel kommer strängar som innehåller ordet "needless" och andra ord som innehåller sekvensen "needle" att visas.


För att tala om för grep att du letar efter ett specifikt ord, använd -w-omkopplaren. Denna nyckel begränsar sökningen till endast det angivna ordet. Ett ord är en fråga som avgränsas på båda sidor av blanksteg, skiljetecken eller radbrytningar.

$ grep -w needle haystack.txt

Det är inte nödvändigt att begränsa sökningen till bara en fil; grep kan söka över en grupp filer, och sökresultaten kommer att indikera filen där matchningen hittades. Omkopplaren -n kommer också att lägga till radnumret där matchningen hittades, och omkopplaren -r låter dig utföra en rekursiv sökning. Detta är mycket praktiskt när du söker bland filer med programkällkoder.

$ grep -rnw funktionsnamn /home/www/dev/myprogram/

Filnamnet kommer att listas före varje matchning. Om du behöver dölja filnamn, använd -h-växeln, tvärtom, om du bara behöver filnamn, ange då -l-växeln
I följande exempel kommer vi att söka efter URL:er i IRC-loggfilen och visa de senaste 10 matchningarna.

$ grep -wo http://.* channel.log | svans

Alternativet -o säger åt grep att bara skriva ut mönstret som matchar istället för hela linjen. Med pipe omdirigerar vi utdata från grep till tail-kommandot, som som standard matar ut de sista 10 raderna.
Nu kommer vi att räkna antalet meddelanden som skickats till irc-kanalen av vissa användare. Till exempel alla meddelanden jag skickat hemifrån och från jobbet. De skiljer sig åt i smeknamn, hemma använder jag smeknamnet user_at_home och på jobbet user_at_work.

$ grep -c "^user_at_(home|work)" channel.log

Med alternativet -c skriver grep bara ut antalet träffar som hittats, inte själva matchningarna. Söksträngen är omgiven av citattecken eftersom den innehåller specialtecken som kan kännas igen av skalet som kontrolltecken. Observera att citattecken inte ingår i sökmönstret. Omvänt snedstreck "" används för att undvika specialtecken.
Låt oss söka efter meddelanden från personer som gillar att "skrika" i kanalen. Med "skrik" menar vi meddelanden skrivna i blond stil, med alla STORA bokstäver. För att utesluta slumpmässiga träffar av förkortningar från sökningen kommer vi att söka efter ord med fem eller fler tecken:

$ grep -w "+(5,)" kanal.log

För en mer detaljerad beskrivning kan du se greps man-sida.
Några fler exempel:

# grep root /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin

Visar rader från filen /etc/passwd som innehåller strängens rot.

# grep -n root /etc/passwd 1:root:x:0:0:root:/root:/bin/bash 12:operatör:x:11:0:operatör:/root:/sbin/nologin

Dessutom visas radnumren som innehåller den sökta raden.

# grep -v bash /etc/passwd | grep -v nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin :/sbin/halt news:x:9:13:news:/var/spool/news: mailnull:x:47:47::/var/spool/mqueue:/dev/null xfs:x:43:43: X Font Server:/etc/X11/fs:/bin/false rpc:x:32:32:Portmapper RPC-användare:/:/bin/false nscd:x:28:28:NSCD Daemon:/:/bin/false named:x:25:25:Named:/var/named:/bin/false squid:x:23:23::/var/spool/squid:/dev/null ldap:x:55:55:LDAP Användare: /var/lib/ldap:/bin/false apache:x:48:48:Apache:/var/www:/bin/false

Kontrollerar vilka användare som inte använder bash, exklusive de användarkonton som har nologin specificerat som sitt skal.

# grep -c false /etc/passwd 7

Räknar antalet konton som har /bin/false som skal.

# grep -i games ~/.bash* | grep -v historik

Detta kommando visar rader från alla filer i hemkatalogen nuvarande användaren, vars namn börjar med ~/.bash, förutom de filer vars namn innehåller stränghistoriken, för att utesluta matchningar som finns i filen ~/.bash_history, som kan ha samma rad i översta eller gemener. Observera att sökningen efter ordet "spel" utförs; du kan ersätta vilket annat ord som helst.
grep kommando och reguljära uttryck

Till skillnad från föregående exempel kommer vi nu bara att visa de rader som börjar med raden "root":

# grep ^root /etc/passwd root:x:0:0:root:/root:/bin/bash

Om vi ​​vill se vilka konton som inte har använt skalet alls, letar vi efter rader som slutar med ett ":"-tecken:

# grep:$ /etc/passwd news:x:9:13:news:/var/spool/news:

För att kontrollera om PATH-variabeln i din ~/.bashrc-fil är exporterad, välj först raderna med "export" och leta sedan efter rader som börjar med raden "PATH"; i detta fall kommer MANPATH och andra inte att visas möjliga sätt:

# grep export ~/.bashrc | grep "PATH" export PATH="/bin:/usr/lib/mh:/lib:/usr/bin:/usr/local/bin:/usr/ucb:/usr/dbin:$PATH"

Karaktärsklasser

Uttrycket inom hakparenteser är en lista över tecken inneslutna inom tecknen [" och "]"". Det matchar alla enstaka tecken som anges i den här listan; om det första tecknet i listan är "^", så matchar det alla tecken som INTE finns i listan. Till exempel matchar det reguljära uttrycket "" vilken enskild siffra som helst.

Inom ett uttryck inom hakparenteser kan du ange ett intervall som består av två tecken åtskilda av ett bindestreck. Då matchar uttrycket vilken singelton som helst som enligt sorteringsreglerna faller inom dessa två tecken, inklusive dessa två tecken; detta tar hänsyn till sorteringen och teckenuppsättningen som anges i lokalen. Till exempel, när standardlokalen är C, motsvarar uttrycket "" uttrycket "". Det finns många lokaler där sortering sker i ordboksordning, och i dessa lokaler är "" i allmänhet inte likvärdigt med "", där det till exempel kan motsvara uttrycket "". För att använda den traditionella tolkningen av uttrycket inom parentes kan du använda C-lokalen genom att ställa in miljövariabeln LC_ALL till "C".

Slutligen finns det speciellt namngivna teckenklasser, som anges i uttryck inom hakparenteser. Ytterligare information För information om dessa fördefinierade uttryck, se man-sidorna eller grep-kommandodokumentationen.

# grep /etc/group sys:x:3:root,bin,adm tty:x:5: mail:x:12:mail,postfix ftp:x:50: nobody:x:99: floppy:x:19: xfs:x:43: nfsnobody:x:65534: postfix:x:89:

Exemplet visar alla rader som innehåller antingen tecknet "y" eller tecknet "f".
Universella tecken (metatecken)

Använda sig av "." för att matcha ett enskilt tecken. Om du vill ha en lista över alla engelska ord hämtade från ordboken som innehåller fem tecken som börjar med "c" och slutar med "h" (användbart för att lösa korsord):

# grep " " /usr/share/dict/words catch clash tyg coach soffa hosta krasch crush

Om du vill visa rader som innehåller ett punkttecken som en bokstavlig, anger du alternativet -F i kommandot grep. Symboler "< " и «>" betyder närvaron av en tom rad före och följaktligen efter de angivna bokstäverna. Det betyder att orden i ordfilen måste skrivas därefter. Om du vill hitta alla ord i texten enligt de angivna mönstren utan att ta hänsyn till tomma rader, utelämna symbolerna "< " и «>", för en mer exakt sökning av endast ord, använd -w-omkopplaren.

För att på liknande sätt hitta ord som kan ha hur många tecken som helst mellan "c" och "h", använd en asterisk (*). I exemplet nedan väljs alla ord som börjar med "c" och slutar med "h" från systemlexikonet:

# grep " " /usr/share/dict/words caliph cash catch cheesecloth cheetah --utgång utelämnad--

Om du vill hitta ett bokstavligt asterisktecken i en fil eller utdataström, använd enstaka citat. Användaren i exemplet nedan försöker först leta efter en "asterisk" i filen /etc/profile utan att använda citattecken, vilket resulterar i att ingenting hittas. När citattecken används utmatas resultatet:

# grep * /etc/profile # grep "*" /etc/profile för i i /etc/profile.d/*.sh ; do

För att fullständigt bearbeta texter i bash-skript med sed och awk behöver du bara förstå reguljära uttryck. Implementeringar av detta mest användbara verktyg kan hittas bokstavligen överallt, och även om alla reguljära uttryck är strukturerade på ett liknande sätt och bygger på samma idéer, har det vissa funktioner att arbeta med dem i olika miljöer. Här kommer vi att prata om reguljära uttryck som är lämpliga att använda i skript kommandorad Linux.

Detta material är tänkt som en introduktion till reguljära uttryck, avsett för dem som kanske är helt omedvetna om vad de är. Så låt oss börja från början.

Vad är reguljära uttryck

Många människor, när de först ser vanliga uttryck, tror genast att de tittar på ett meningslöst virrvarr av karaktärer. Men detta är naturligtvis långt ifrån fallet. Ta en titt på detta regex till exempel


Enligt vår åsikt kommer även en absolut nybörjare omedelbart att förstå hur det fungerar och varför det behövs :) Om du inte riktigt förstår det, läs bara vidare och allt kommer att falla på plats.
Ett reguljärt uttryck är ett mönster som program som sed eller awk använder för att filtrera text. Mallar använder vanliga ASCII-tecken som representerar sig själva, och så kallade metatecken som spelar en speciell roll, t.ex. tillåter referenser till vissa grupper av tecken.

Typer av reguljära uttryck

Implementeringar av reguljära uttryck i olika miljöer, till exempel i programmeringsspråk som Java, Perl och Python, och i Linux-verktyg som sed, awk och grep, har vissa funktioner. Dessa funktioner är beroende av så kallade reguljära uttrycksmotorer, som tolkar mönster.
Linux har två reguljära uttrycksmotorer:
  • En motor som stöder standarden POSIX Basic Regular Expression (BRE).
  • En motor som stöder standarden POSIX Extended Regular Expression (ERE).
De flesta Linux-verktyg överensstämmer med åtminstone POSIX BRE-standarden, men vissa verktyg (inklusive sed) förstår bara en delmängd av BRE-standarden. En av anledningarna till denna begränsning är önskan att göra sådana verktyg så snabbt som möjligt vid textbehandling.

POSIX ERE-standarden implementeras ofta i programmeringsspråk. Det låter dig använda stor mängd verktyg för att utveckla reguljära uttryck. Det kan till exempel vara speciella teckensekvenser för ofta använda mönster, som att söka efter enskilda ord eller uppsättningar siffror i text. Awk stöder ERE-standarden.

Det finns många sätt att utveckla reguljära uttryck, beroende både på programmerarens åsikt och på funktionerna i motorn som de är skapade för. Det är inte lätt att skriva universella reguljära uttryck som vilken motor som helst kan förstå. Därför kommer vi att fokusera på de vanligaste reguljära uttrycken och titta på funktionerna i deras implementering för sed och awk.

POSIX BRE reguljära uttryck

Det kanske enklaste BRE-mönstret är ett reguljärt uttryck för att söka efter den exakta förekomsten av en sekvens av tecken i text. Så här ser det ut att söka efter en sträng i sed och awk:

$ echo "Detta är ett test" | sed -n "/test/p" $ echo "Detta är ett test" | awk "/test/(print $0)"

Hitta text efter mönster i sed


Hitta text efter mönster i awk

Du kanske märker att sökningen efter ett givet mönster utförs utan att ta hänsyn till den exakta platsen för texten i raden. Dessutom spelar antalet händelser ingen roll. Efter det reguljära uttrycket hittar given text var som helst i linjen anses linjen vara lämplig och skickas vidare för vidare bearbetning.

När du arbetar med reguljära uttryck måste du ta hänsyn till att de är skiftlägeskänsliga:

$ echo "Detta är ett test" | awk "/Test/(print $0)" $ echo "Detta är ett test" | awk "/test/(print $0)"

Reguljära uttryck är skiftlägeskänsliga

Det första reguljära uttrycket hittade inga matchningar eftersom ordet "test", som börjar med en stor bokstav, inte förekommer i texten. Den andra, konfigurerad för att söka efter ett ord skrivet med versaler, hittade en lämplig rad i strömmen.

I reguljära uttryck kan du inte bara använda bokstäver utan även mellanslag och siffror:

$ echo "Detta är ett test 2 igen" | awk "/test 2/(print $0)"

Hitta ett stycke text som innehåller mellanslag och siffror

Mellanslag behandlas som vanliga tecken av motorn för reguljära uttryck.

Särskilda symboler

Använder sig av olika karaktärer I reguljära uttryck måste du ta hänsyn till vissa funktioner. Det finns alltså några specialtecken, eller metatecken, vars användning i en mall kräver ett speciellt tillvägagångssätt. Här är de:

.*^${}\+?|()
Om en av dem behövs i mallen, kommer den att behöva escapes med ett snedstreck (omvänt snedstreck) - \ .

Om du till exempel behöver hitta ett dollartecken i texten måste du inkludera det i mallen, föregås av ett escape-tecken. Låt oss säga att det finns en fil myfile med följande text:

Det finns 10$ på min ficka
Dollartecknet kan upptäckas med detta mönster:

$awk "/\$/(skriv ut $0)" min fil

Använda ett specialtecken i ett mönster

Dessutom är omvänt snedstreck också ett specialtecken, så om du behöver använda det i ett mönster kommer det också att behöva escapes. Det ser ut som två snedstreck som följer efter varandra:

$ echo "\ är ett specialtecken" | awk "/\\/(skriv ut $0)"

Undviker ett snedstreck

Även om snedstrecket inte ingår i listan över specialtecken ovan, kommer ett försök att använda det i ett reguljärt uttryck skrivet för sed eller awk att resultera i ett fel:

$ echo "3/2" | awk "///(print $0)"

Felaktig användning av snedstreck i ett mönster

Om det behövs måste det också undvikas:

$ echo "3/2" | awk "/\//(skriv ut $0)"

Undviker ett snedstreck framåt

Ankare symboler

Det finns två specialtecken för att länka ett mönster till början eller slutet av en textsträng. Captecknet - ^ låter dig beskriva sekvenser av tecken som finns i början av textrader. Om mönstret du letar efter finns någon annanstans i strängen kommer det reguljära uttrycket inte att svara på det. Användningen av denna symbol ser ut så här:

$ echo "välkommen till likegeeks hemsida" | awk "/^likegeeks/(skriv ut $0)" $ echo "likegeeks hemsida" | awk "/^likegeeks/(print $0)"

Hitta ett mönster i början av en sträng

Tecknet ^ är utformat för att söka efter ett mönster i början av en rad, medan fallet med tecken också beaktas. Låt oss se hur detta påverkar behandlingen av en textfil:

$awk "/^this/(skriv ut $0)" min fil


Hitta ett mönster i början av en rad i text från en fil

När du använder sed, om du placerar en keps någonstans inuti mönstret, kommer den att behandlas som vilken annan vanlig karaktär som helst:

$ echo "Detta ^ är ett test" | sed -n "/s ^/p"

Keps inte i början av mönstret i sed

I awk, när du använder samma mall, måste detta tecken escapes:

$ echo "Detta ^ är ett test" | awk "/s\^/(skriv ut $0)"

Täck inte i början av mallen i awk

Vi har listat ut sökningen efter textfragment som finns i början av en rad. Vad händer om du behöver hitta något i slutet av en rad?

Dollartecknet - $, som är ankartecknet för slutet av raden, hjälper oss med detta:

$ echo "Detta är ett test" | awk "/test$/(print $0)"

Hitta text i slutet av en rad

Du kan använda båda ankarsymbolerna i samma mall. Låt oss bearbeta filen myfile, vars innehåll visas i figuren nedan, med hjälp av följande reguljära uttryck:

$ awk "/^detta är en test$/(skriv ut $0)" min fil


Ett mönster som använder specialtecken för att starta och avsluta en rad

Som du kan se svarade mallen endast på en rad som helt motsvarade den givna sekvensen av tecken och deras plats.

Så här filtrerar du bort tomma rader med ankartecken:

$awk "!/^$/(skriv ut $0)" min fil
I den här mallen använde jag en negationssymbol, ett utropstecken - ! . Genom att använda detta mönster söker man efter linjer som inte innehåller något mellan början och slutet av raden, och tack vare utropstecken Endast linjer som inte matchar detta mönster skrivs ut.

Punktsymbol

Perioden används för att matcha ett enskilt tecken utom nyradstecknet. Låt oss skicka filen myfile till detta reguljära uttryck, vars innehåll anges nedan:

$awk "/.st/(skriv ut $0)" min fil


Använda en prick i reguljära uttryck

Som kan ses av utdata, motsvarar endast de två första raderna från filen mönstret, eftersom de innehåller sekvensen av tecken "st" föregås av ett annat tecken, medan den tredje raden inte innehåller en lämplig sekvens, och fjärde har det, men är med i början av raden.

Karaktärsklasser

En prick matchar varje enskilt tecken, men vad händer om du vill vara mer flexibel när det gäller att begränsa uppsättningen tecken du letar efter? I den här situationen kan du använda karaktärsklasser.

Tack vare detta tillvägagångssätt kan du organisera en sökning efter vilken karaktär som helst från en given uppsättning. För att beskriva en teckenklass används hakparenteser:

$awk "/th/(skriv ut $0)" min fil


Beskrivning av en teckenklass i ett reguljärt uttryck

Här letar vi efter en sekvens av "te" tecken som föregås av ett "o"-tecken eller ett "i"-tecken.

Klasser är praktiska när du söker efter ord som kan börja med antingen en stor eller liten bokstav:

$ echo "det här är ett test" | awk "/hans är ett test/(skriv ut $0)" $ echo "Detta är ett test" | awk "/hans är ett test/(skriv ut $0)"

Sök efter ord som kan börja med en liten eller stor bokstav

Karaktärsklasser är inte begränsade till bokstäver. Andra symboler kan användas här. Det är omöjligt att säga i förväg i vilken situation klasser kommer att behövas - allt beror på att problemet löses.

Negation av karaktärsklasser

Teckenklasser kan också användas för att lösa det omvända problemet som beskrivs ovan. Istället för att söka efter symboler som ingår i en klass kan du nämligen organisera en sökning efter allt som inte ingår i klassen. För att uppnå detta reguljära uttrycksbeteende måste du placera ett ^-tecken framför listan med klasstecken. Det ser ut så här:

$ awk "/[^oi]th/(print $0)" min fil


Hitta karaktärer som inte ingår i en klass

I det här fallet kommer sekvenser av "te" tecken att hittas som föregås av varken "o" eller "i".

Karaktärsintervall

I teckenklasser kan du beskriva teckenintervall med hjälp av bindestreck:

$awk "/st/(skriv ut $0)" min fil


Beskrivning av ett antal tecken i en teckenklass

I i detta exempel det reguljära uttrycket svarar på sekvensen av tecken "st" som föregås av ett tecken som finns i alfabetisk ordning, mellan tecknen "e" och "p".

Områden kan också skapas från siffror:

$ echo "123" | awk "//" $ echo "12a" | awk "//"

Reguljärt uttryck för att hitta valfria tre tal

En teckenklass kan inkludera flera intervall:

$awk "/st/(skriv ut $0)" min fil


En teckenklass som består av flera intervall

Detta reguljära uttryck hittar alla sekvenser av "st" som föregås av tecken från intervallen a-f och m-z.

Specialkaraktärsklasser

BRE har speciella teckenklasser som du kan använda när du skriver reguljära uttryck:
  • [[:alpha:]] - matchar alla alfabetiska tecken, skrivna med stora eller små bokstäver.
  • [[:alnum:]] - matchar alla alfanumeriska tecken, nämligen tecken i intervallen 0-9 , A-Z , a-z .
  • [[:blank:]] - matchar ett mellanslag och ett tabbtecken.
  • [[:siffra:]] - valfritt tecken från 0 till 9.
  • [[:upper:]] - stora bokstäver - A-Z .
  • [[:lower:]] - små bokstäver - a-z .
  • [[:print:]] - matchar alla utskrivbara tecken.
  • [[:punct:]] - matchar skiljetecken.
  • [[:Plats:]] - blanksteg, i synnerhet - mellanslag, tab, tecken NL, FF, VT, CR.
Du kan använda specialklasser i mallar så här:

$ echo "abc" | awk "/[[:alpha:]]/(print $0)" $ echo "abc" | awk "/[[:digit:]]/(print $0)" $ echo "abc123" | awk "/[[:siffra:]]/(skriv ut $0)"


Specialteckenklasser i reguljära uttryck

Stjärnsymbol

Om du placerar en asterisk efter ett tecken i ett mönster kommer det att innebära att det reguljära uttrycket fungerar om tecknet förekommer i strängen hur många gånger som helst - inklusive situationen när tecknet saknas i strängen.

$ echo "test" | awk "/tes*t/(skriv ut $0)" $ echo "tessst" | awk "/tes*t/(skriv ut $0)"


Använda tecknet * i reguljära uttryck

Detta jokertecken används vanligtvis för ord som ständigt stavas fel eller för ord som är föremål för olika varianter korrekt stavning:

$ echo "Jag gillar grön färg" | awk "/colou*r/(print $0)" $ echo "Jag gillar grön färg " | awk "/colou*r/(print $0)"

Hitta ett ord med olika stavningar

I det här exemplet svarar samma reguljära uttryck på både ordet "färg" och ordet "färg". Detta beror på det faktum att tecknet "u", följt av en asterisk, antingen kan vara frånvarande eller visas flera gånger i rad.

En annan användbar funktion som kommer från asterisksymbolen är att kombinera den med en prick. Denna kombination låter det reguljära uttrycket svara på valfritt antal tecken:

$ awk "/this.*test/(print $0)" min fil


En mall som svarar på valfritt antal tecken

I det här fallet spelar det ingen roll hur många och vilka tecken som finns mellan orden "detta" och "testa".

Asterisken kan också användas med teckenklasser:

$ echo "st" | awk "/s*t/(print $0)" $ echo "sat" | awk "/s*t/(print $0)" $ echo "set" | awk "/s*t/(print $0)"


Använda en asterisk med teckenklasser

I alla tre exemplen fungerar det reguljära uttrycket eftersom asterisken efter teckenklassen betyder att om valfritt antal "a" eller "e" tecken hittas, eller om inga hittas, kommer strängen att matcha det givna mönstret.

POSIX ERE reguljära uttryck

POSIX ERE-mallarna som vissa Linux-verktyg stöder kan innehålla ytterligare tecken. Som redan nämnts stöder awk denna standard, men sed gör det inte.

Här kommer vi att titta på de vanligaste symbolerna i ERE-mönster, som kommer att vara användbara för dig när du skapar dina egna reguljära uttryck.

▍Frågetecken

Ett frågetecken anger att det föregående tecknet kan förekomma en gång eller inte alls i texten. Den här karaktären är en av upprepningsmetakaraktärerna. Här är några exempel:

$ echo "tet" | awk "/tes?t/(print $0)" $ echo "test" | awk "/tes?t/(print $0)" $ echo "testst" | awk "/tes?t/(print $0)"


Frågetecken i reguljära uttryck

Som du kan se, i det tredje fallet visas bokstaven "s" två gånger, så det reguljära uttrycket svarar inte på ordet "testst".

Frågetecknet kan också användas med teckenklasser:

$ echo "tst" | awk "/t?st/(print $0)" $ echo "test" | awk "/t?st/(print $0)" $ echo "tast" | awk "/t?st/(print $0)" $ echo "taest" | awk "/t?st/(print $0)" $ echo "test" | awk "/t?st/(print $0)"


Frågetecken och karaktärsklasser

Om det inte finns några tecken från klassen på raden, eller ett av dem förekommer en gång, fungerar det reguljära uttrycket, men så fort två tecken dyker upp i ordet hittar systemet inte längre en matchning för mönstret i texten.

▍Plussymbol

Plustecknet i mönstret indikerar att det reguljära uttrycket kommer att matcha det det letar efter om det föregående tecknet förekommer en eller flera gånger i texten. Denna konstruktion kommer dock inte att reagera på frånvaron av en symbol:

$ echo "test" | awk "/te+st/(print $0)" $ echo "teest" | awk "/te+st/(print $0)" $ echo "tst" | awk "/te+st/(print $0)"


Plussymbolen i reguljära uttryck

I det här exemplet, om det inte finns något "e"-tecken i ordet, hittar inte motorn för reguljära uttryck matchningar med mönstret i texten. Plussymbolen fungerar också med teckenklasser - på så sätt liknar den asterisken och frågetecknet:

$ echo "tst" | awk "/t+st/(print $0)" $ echo "test" | awk "/t+st/(print $0)" $ echo "teast" | awk "/t+st/(print $0)" $ echo "teeast" | awk "/t+st/(print $0)"


Plus tecken och tecken klasser

I det här fallet, om raden innehåller något tecken från klassen, kommer texten att anses matcha mönstret.

▍Kulliga hängslen

Lockiga hängslen, som kan användas i ERE-mönster, liknar symbolerna som diskuterats ovan, men de låter dig mer exakt specificera det antal förekomster som krävs av symbolen som föregår dem. Du kan ange en begränsning i två format:
  • n - ett nummer som anger det exakta antalet sökta förekomster
  • n, m är två tal som tolkas enligt följande: "minst n gånger, men inte mer än m."
Här är exempel på det första alternativet:

$ echo "tst" | awk "/te(1)st/(print $0)" $ echo "test" | awk "/te(1)st/(print $0)"

Lockiga hängslen i mönster, söker efter det exakta antalet förekomster

I äldre versioner av awk var du tvungen att använda kommandoradsalternativet --re-interval för att få programmet att känna igen intervall i reguljära uttryck, men i nyare versioner är detta inte nödvändigt.

$ echo "tst" | awk "/te(1,2)st/(print $0)" $ echo "test" | awk "/te(1,2)st/(print $0)" $ echo "teest" | awk "/te(1,2)st/(print $0)" $ echo "teeest" | awk "/te(1,2)st/(print $0)"


Avstånd specificerat i lockiga hängslen

I det här exemplet måste tecknet "e" visas 1 eller 2 gånger på raden, då kommer det reguljära uttrycket att svara på texten.

Lockiga hängslen kan också användas med karaktärsklasser. De principer du redan känner till gäller här:

$ echo "tst" | awk "/t(1,2)st/(print $0)" $ echo "test" | awk "/t(1,2)st/(print $0)" $ echo "test" | awk "/t(1,2)st/(print $0)" $ echo "teeast" | awk "/t(1,2)st/(print $0)"


Lockiga hängslen och karaktärsklasser

Mallen kommer att reagera på texten om den innehåller tecknet "a" eller tecknet "e" en eller två gånger.

▍Logisk "eller"-symbol

Symbol | - en vertikal stapel betyder ett logiskt "eller" i reguljära uttryck. Vid bearbetning av ett reguljärt uttryck som innehåller flera fragment åtskilda av ett sådant tecken, kommer motorn att anse den analyserade texten som lämplig om den matchar något av fragmenten. Här är ett exempel:

$ echo "Detta är ett test" | awk "/test|exam/(print $0)" $ echo "Detta är en tentamen" | awk "/test|exam/(print $0)" $ echo "Detta är något annat" | awk "/test|exam/(print $0)"


Logiskt "eller" i reguljära uttryck

I det här exemplet är det reguljära uttrycket konfigurerat för att söka i texten efter orden "test" eller "examen". Observera att mellan mallfragmenten och symbolen som skiljer dem | det ska inte finnas några mellanslag.

Reguljära uttrycksfragment kan grupperas med hjälp av parenteser. Om du grupperar en viss teckensekvens kommer den att uppfattas av systemet som en vanlig karaktär. Det vill säga att till exempel upprepningsmetakaraktärer kan appliceras på den. Så här ser det ut:

$ echo "Gilla" | awk "/Like(Geeks)?/(print $0)" $ echo "LikeGeeks" | awk "/Like(Geeks)?/(print $0)"


Gruppera reguljära uttrycksfragment

I dessa exempel är ordet "nördar" inom parentes, följt av ett frågetecken. Kom ihåg att ett frågetecken betyder "0 eller 1 upprepning", så det reguljära uttrycket kommer att svara på både strängen "Gilla" och strängen "LikeGeeks."

Praktiska exempel

Nu när vi har täckt grunderna i reguljära uttryck är det dags att göra något användbart med dem.

▍Räknar antalet filer

Låt oss skriva ett bash-skript som räknar filer som finns i kataloger som är skrivna till en variabel miljö PATH. För att göra detta måste du först skapa en lista med katalogsökvägar. Låt oss göra detta med hjälp av sed, och ersätter kolon med mellanslag:

$ echo $PATH | sed "s/:/ /g"
Kommandot ersätt stöder reguljära uttryck som mönster för att söka text. I det här fallet är allt extremt enkelt, vi letar efter kolonsymbolen, men ingen stör oss att använda något annat här - allt beror på den specifika uppgiften.
Nu måste du gå igenom den resulterande listan i en slinga och utföra de åtgärder som krävs för att räkna antalet filer. Den allmänna konturen av skriptet kommer att se ut så här:

Mypath=$(echo $PATH | sed "s/:/ /g") för katalogen i $mypath gör klart
Låt oss nu skriva hela skriptets text genom att använda kommandot ls för att få information om antalet filer i varje katalog:

#!/bin/bash mypath=$(echo $PATH | sed "s/:/ /g") count=0 för katalog i $mypath do check=$(ls $katalog) för objekt i $check do count=$ [ $count + 1 ] klart echo "$directory - $count" count=0 gjort
När man kör skriptet kan det visa sig att vissa kataloger från PATH inte finns, men detta hindrar inte det från att räkna filer i befintliga kataloger.


Filräkning

Huvudvärdet av detta exempel är att med samma tillvägagångssätt kan du lösa mycket mer komplexa problem. Vilka exakt beror på dina behov.

▍Verifiera e-postadresser

Det finns webbplatser med enorma samlingar av reguljära uttryck som låter dig kontrollera adresser E-post, telefonnummer, och så vidare. Men det är en sak att ta något färdigt och en helt annan att skapa något själv. Så låt oss skriva ett reguljärt uttryck för att kontrollera e-postadresser. Låt oss börja med att analysera källdata. Här är till exempel en viss adress:

[e-postskyddad]
Användarnamnet, användarnamnet, kan bestå av alfanumeriska och några andra tecken. Detta är nämligen en prick, ett streck, ett understreck, ett plustecken. Användarnamnet följs av ett @-tecken.

Beväpnad med denna kunskap, låt oss börja montera det reguljära uttrycket från dess vänstra sida, som används för att kontrollera användarnamnet. Här är vad vi fick:

^(+)@
Detta reguljära uttryck kan läsas på följande sätt: "Roden måste börja med minst ett tecken från de i gruppen som anges inom hakparenteser, följt av ett @-tecken."

Nu - värdnamnet kö - värdnamn . Samma regler gäller här som för användarnamnet, så mallen för det kommer att se ut så här:

(+)
Toppdomännamnet är föremål för särskilda regler. Det kan bara finnas alfabetiska tecken, av vilka det måste finnas minst två (till exempel innehåller sådana domäner vanligtvis en landskod), och inte fler än fem. Allt detta betyder att mallen för att kontrollera den sista delen av adressen blir så här:

\.({2,5})$
Du kan läsa det så här: "Först måste det finnas en punkt, sedan 2 till 5 alfabetiska tecken, och efter det slutar raden."

Efter att ha förberett mallar för enskilda delar av det reguljära uttrycket, låt oss sätta ihop dem:

^(+)@(+)\.({2,5})$
Nu återstår bara att testa vad som hände:

$ echo" [e-postskyddad]" | awk "/^(+)@(+)\.((2,5))$/(print $0)" $ echo " [e-postskyddad]" | awk "/^(+)@(+)\.((2,5))$/(skriv ut $0)"


Validera en e-postadress med reguljära uttryck

Det faktum att texten som skickas till awk visas på skärmen betyder att systemet kände igen den som en e-postadress.

Resultat

Om det reguljära uttrycket för att kontrollera e-postadresser som du stötte på i början av artikeln verkade helt obegripligt då, hoppas vi att det nu inte längre ser ut som en meningslös uppsättning tecken. Om det verkligen är så betyder det detta material uppfyllt sitt syfte. Faktum är att reguljära uttryck är ett ämne som du kan studera hela livet, men även det lilla som vi har täckt kan redan hjälpa dig att skriva manus som bearbetar texter ganska avancerade.

I denna serie av material visade vi vanligtvis mycket enkla exempel bash-skript som bestod av bokstavligen flera rader. Nästa gång ska vi titta på något större.

Kära läsare! Använder du reguljära uttryck när du bearbetar text i kommandoradsskript?

Ett av de mest användbara och funktionsrika teamen i Linux terminal– kommandot "grep". Grep är en akronym som står för "global regular expression print" (det vill säga "sök överallt efter strängar som matchar ett reguljärt uttryck och skriv ut dem"). Detta innebär att grep kan användas för att se om indata matchar specificerade mönster.

Detta till synes triviala program är mycket kraftfullt när det används på rätt sätt. Dess förmåga att sortera indata baserat på komplexa regler gör den till en populär länk i många kommandokedjor.

Den här handledningen tittar på några av grep-kommandots funktioner och går sedan vidare till att använda reguljära uttryck. Allt beskrivs i denna manual tekniker kan användas för att hantera en virtuell server.

Grunderna för användning

I sin enklaste form används grep för att hitta matchningar av bokstavsmönster i en textfil. Detta betyder att om grep ges ett sökord, kommer det att skriva ut varje rad i filen som innehåller det ordet.

Som ett exempel kan du använda grep för att hitta rader som innehåller ordet "GNU" i version 3 av GNU General Public License på ett Ubuntu-system.

cd /usr/share/common-licenses
grep "GNU" GPL-3
GNU GENERAL OFFENTLIG LICENS





13. Använd med GNU Affero General Public License.
under version 3 av GNU Affero General Public License till en singel
...
...

Det första argumentet, "GNU", är mönstret att söka efter, och det andra argumentet, "GPL-3", är indatafilen som ska hittas.

Som ett resultat kommer alla rader som innehåller textmönstret att matas ut. I några Linux-distributioner mönstret du letar efter kommer att markeras i utdataraderna.

Generella val

Som standard söker kommandot grep helt enkelt efter strikt specificerade mönster i inmatningsfilen och skriver ut raderna som det hittar. Men greps beteende kan ändras genom att lägga till några ytterligare flaggor.

Om du behöver ignorera sökparameterns skiftläge och söka efter varianter av både versaler och gemener av mönstret, kan du använda verktygen "-i" eller "--ignore-case".

Som ett exempel kan du använda grep för att söka i samma fil efter ordet "licens" skrivet med versaler, gemener eller blandade bokstäver.

grep -i "license" GPL-3
GNU GENERAL OFFENTLIG LICENS
i detta licensdokument, men det är inte tillåtet att ändra det.
GNU General Public License är en gratis copyleft-licens för
Licenserna för de flesta programvaror och andra praktiska arbeten är utformade
GNU General Public License är avsedd att garantera din frihet att
GNU General Public License för de flesta av vår programvara; det gäller också


"Denna licens" hänvisar till version 3 av GNU General Public License.
"Programmet" hänvisar till alla upphovsrättsskyddade verk som licensieras under detta
...
...

Som du kan se innehåller utgången "LICENS", "licens" och "Licens". Om det fanns en instans av "LiCeNsE" i filen, skulle den också matas ut.
Om du behöver hitta alla linjer som inte innehåller det angivna mönstret kan du använda flaggorna "-v" eller "--invert-match".

Som ett exempel kan du använda följande kommando för att söka i BSD-licensen efter alla rader som inte innehåller ordet "the":

grep -v "the" BSD
Alla rättigheter förbehållna.
Omfördelning och användning i källform och binär form, med eller utan
är uppfyllda:
kan användas för att rekommendera eller marknadsföra produkter som härrör från denna programvara
utan särskilt skriftligt tillstånd i förväg.
DENNA PROGRAM TILLHANDAHÅLLS AV REGENTERNA OCH BIDRAGARE "I BEFINTLIGT SKICK"""
NÅGRA UTTRYCKTA ELLER UNDERFÖRSTÅDDA GARANTIER, INKLUSIVE, MEN INTE BEGRÄNSADE TILL,
...
...

Som du kan se matades de två sista raderna ut som att de inte innehöll ordet "the" eftersom kommandot "ignore case" inte användes.

Det är alltid bra att veta radnumren där matchningarna hittades. De kan hittas med flaggorna "-n" eller "--line-number".

Om du använder denna flagga i föregående exempel kommer följande resultat att visas:

grep -vn "the" BSD
2: Alla rättigheter reserverade.
3:
4:Omfördelning och användning i källform och binär form, med eller utan
6:är uppfyllda:
13: kan användas för att rekommendera eller marknadsföra produkter som härrör från denna programvara
14: utan särskilt skriftligt tillstånd.
15:
16:DEN HÄR PROGRAMVARAN TILLHANDAHÅLLS AV REGENTERNA OCH BIDRAGARE "I BEFINTLIGT SKICK"""
17: EVENTUELLA UTTRYCKLIGA ELLER UNDERFÖRSTÅDDA GARANTIER, INKLUSIVE, MEN INTE BEGRÄNSADE TILL,
...
...

Du kan nu hänvisa till radnumret när du behöver göra ändringar på varje rad som inte innehåller "the".

Vanliga uttryck

Som nämnts i inledningen står grep för "global regular expression print". Ett reguljärt uttryck är en textsträng som beskriver ett specifikt sökmönster.

Olika applikationer och programmeringsspråk använder reguljära uttryck lite olika. Denna handledning täcker bara en liten del av sätt att beskriva mönster för Grep.

Bokstäver matchar

I exemplen ovan på att söka efter orden "GNU" och "the", letade man efter mycket enkla reguljära uttryck som exakt matchade teckensträngen "GNU" och "the".

Det är mer korrekt att tänka på dem som matchningar av teckensträngar snarare än som matchningar av ord. När du väl blir bekant med mer komplexa mönster kommer denna distinktion att bli mer betydelsefull.

Mönster som exakt matchar givna tecken kallas "bokstavsmönster" eftersom de matchar mönstret bokstav för bokstav, tecken för tecken.

Alla alfabetiska och numeriska tecken (och vissa andra tecken) matchar bokstavligen om de inte har modifierats av andra uttrycksmekanismer.

Ankarmatcher

Ankare är specialtecken som indikerar platsen i en sträng för den önskade matchningen.

Du kan till exempel ange att sökningen bara behöver rader som innehåller ordet "GNU" i början. För att göra detta måste du använda ankaret "^" före bokstavssträngen.

Detta exempel skriver bara ut rader som innehåller ordet "GNU" i början.

grep "^GNU" GPL-3
GNU General Public License för de flesta av vår programvara; det gäller också
GNU General Public License, du kan välja vilken version som helst som någonsin publicerats

På samma sätt kan ankaret "$" användas efter en bokstavlig sträng för att indikera att matchningen endast är giltig om teckensträngen som söks på är i slutet av textsträngen.

Följande reguljära uttryck skriver bara ut de rader som innehåller "och" i slutet:

grep "och$" GPL-3
att det inte finns någon garanti för denna gratis programvara. För både användare" och
De exakta villkoren för kopiering, distribution och


alternativ tillåts endast ibland och icke-kommersiellt, och
nätverk kan nekas när själva ändringen materiellt och
negativt påverkar driften av nätverket eller bryter mot reglerna och
provisoriskt, om inte och tills upphovsrättsinnehavaren uttryckligen och
får en licens från de ursprungliga licensgivarna för att köra, ändra och
göra, använda, sälja, erbjuda till försäljning, importera och på annat sätt driva, modifiera och

Matcha vilken karaktär som helst

Punkten (.) används i reguljära uttryck för att indikera att vilket tecken som helst kan visas på den angivna platsen.

Om du till exempel vill hitta matchningar som innehåller två tecken och sedan sekvensen "cept", skulle du använda följande mönster:

grep "..cept" GPL-3
användning, vilket är just där det är mest oacceptabelt. Därför, vi
intrång enligt tillämplig upphovsrättslagstiftning, förutom att verkställa den på en
talar om för användaren att det inte finns någon garanti för arbetet (förutom till

form av en separat skriftlig licens, eller anges som undantag;
Du får inte sprida eller modifiera ett täckt verk annat än uttryckligen
9. Godkännande krävs inte för att ha kopior.
...
...

Som du kan se inkluderar resultaten orden "acceptera" och "utom", såväl som varianter av dessa ord. Mönstret skulle också matcha sekvensen "z2cept" om det fanns i texten.

Uttryck inom parentes

Genom att placera en grupp tecken inom hakparenteser ("") kan du indikera att vilket som helst av tecknen inom hakparenteserna kan visas på den positionen.

Det betyder att om du behöver hitta strängar som innehåller "för" eller "två", kan du kort ange dessa varianter med hjälp av följande mönster:

grep "till" GPL-3
dina program också.

Utvecklare som använder GNU GPL skyddar dina rättigheter med två steg:
ett datornätverk, utan överföring av en kopia, förmedlar inte.

Motsvarande källa från en nätverksserver utan kostnad.
...
...

Som du kan se hittades båda varianterna i filen.

Att sätta tecken inom parentes ger också flera användbara funktioner. Du kan indikera att allt utom tecknen inom parentes matchar mönstret genom att starta listan med tecken inom parentes med tecknet "^".

Det här exemplet använder mönstret ".ode", som inte får matcha "kod"-sekvensen.

grep "[^c]ode" GPL-3
1. Källkod.
modell, för att ge alla som har objektkoden antingen (1) a
det enda betydande användningssättet för produkten.
märk så här när den startar i ett interaktivt läge:

Det är värt att notera att den andra radens utdata innehåller ordet "kod". Detta är inte ett regex- eller grep-fel.

Den här raden skrevs snarare ut eftersom den också innehåller den mönstermatchande sekvensen "läge" som finns i ordet "modell". Det vill säga att snöret trycktes för att det matchade mönstret.

En till användbar funktion hakparenteser - möjligheten att ange ett teckenintervall istället för att ange varje tecken separat.

Det betyder att om du behöver hitta varje rad som börjar med en stor bokstav kan du använda följande mönster:

grep "^" GPL-3
GNU General Public License för de flesta av vår programvara; det gäller också

Licens. Varje licenstagare tilltalas som "du". "Licenser" och


Systembibliotek, eller allmänna verktyg eller allmänt tillgängliga gratis
Källa.

...
...

På grund av vissa inneboende sorteringsproblem är det bättre att använda POSIX-teckenklasser för mer exakta resultat istället för teckenintervallet som används i exemplet ovan.
Det finns många teckenklasser som inte tas upp i denna handbok; till exempel, för att utföra samma procedur som i exemplet ovan, kan du använda teckenklassen "[:upper:]" inom parentes.

grep "^[[:upper:]]" GPL-3
GNU General Public License för de flesta av vår programvara; det gäller också
Stater bör inte tillåta patent att begränsa utveckling och användning av
Licens. Varje licenstagare tilltalas som "du". "Licenser" och
Komponent, och (b) tjänar endast till att möjliggöra användning av arbetet med det
Huvudkomponent, eller för att implementera ett standardgränssnitt för vilket en
Systembibliotek, eller allmänna verktyg eller allmänt tillgängliga gratis
Källa.
Användarprodukten överförs till mottagaren för all framtid eller för en
...
...

Upprepa mönstret (0 eller fler gånger)

En av de vanligaste metatecken är "*"-symbolen, som betyder "upprepa föregående tecken eller uttryck 0 eller fler gånger."

Om du till exempel vill hitta varje rad med öppnande eller avslutande parenteser som bara innehåller bokstäver och enstaka mellanslag mellan dem, kan du använda följande uttryck:

grep "(*)" GPL-3

distribution (med eller utan ändring), tillgängliggörande för
än verket som helhet, som (a) ingår i den normala formen av
Komponent, och (b) tjänar endast till att möjliggöra användning av arbetet med det
(om någon) som det körbara verket körs på, eller en kompilator som används för
(inklusive ett fysiskt distributionsmedium), tillsammans med
(inklusive ett fysiskt distributionsmedium), åtföljd av en
plats (gratis eller mot en avgift), och erbjuda likvärdig tillgång till
...
...

Hur man undviker metatecken

Ibland kan du behöva leta efter en bokstavlig period eller en bokstavlig öppen parentes. Eftersom dessa tecken har en specifik betydelse i reguljära uttryck, måste du "fly" dem genom att tala om för grep att deras speciella betydelse inte behövs i det här fallet.

Dessa tecken kan escapes genom att använda ett omvänt snedstreck (\) före tecknet, vilket vanligtvis har speciell betydelse.

Om du till exempel behöver hitta en sträng som börjar med stor bokstav och slutar med punkt kan du använda uttrycket nedan. Omvänt snedstreck före den sista punkten talar om för kommandot att "escape" det, så att den sista punkten representerar en bokstavlig punkt och inte har någon betydelse för "något tecken":

grep "^.*\.$" GPL-3
Källa.
Licens genom att göra undantag från ett eller flera av dess villkor.
Licens skulle vara att helt avstå från att förmedla programmet.
ALL NÖDVÄNDIG SERVICE, REPARATION ELLER KORREKTION.
SÅDANA SKADOR.
Lägg även till information om hur du kontaktar dig via e-post och papperspost.

Avancerade reguljära uttryck

Grep-kommandot kan också användas med ett utökat reguljärt uttrycksspråk genom att använda flaggan -E eller genom att anropa kommandot egrep istället för grep.

Dessa kommandon öppnar möjligheterna för "utökade reguljära uttryck". Utökade reguljära uttryck inkluderar alla grundläggande metatecken, såväl som ytterligare metatecken för att uttrycka mer komplexa matchningar.

Gruppering

En av de enklaste och mest användbara funktionerna som utökade reguljära uttryck ger är möjligheten att gruppera uttryck och använda dem som en enda enhet.

Parenteser används för att gruppera uttryck. Om du behöver använda parenteser utanför utökade reguljära uttryck kan de "escapes" med ett omvänt snedstreck

grep "\(gruppering\)" file.txt
grep -E "(gruppering)" file.txt
egrep "(gruppering)" file.txt

Ovanstående uttryck är likvärdiga.

Alternering

Precis som hakparenteser anger olika möjliga matchningar för ett enstaka tecken, låter interfoliering dig ange alternativa matchningar för teckensträngar eller uppsättningar uttryck.

Den vertikala strecksymbolen "|" används för att indikera växling. Alternering används ofta i gruppering för att indikera att ett av två eller flera möjliga alternativ ska betraktas som en matchning.

I det här exemplet måste du leta efter "GPL" eller "General Public License":

grep -E "(GPL|General Public License)" GPL-3
GNU General Public License är en gratis copyleft-licens för
GNU General Public License är avsedd att garantera din frihet att
GNU General Public License för de flesta av vår programvara; det gäller också
pris. Våra allmänna offentliga licenser är utformade för att säkerställa att du
Utvecklare som använder GNU GPL skyddar dina rättigheter med två steg:
För skyddet av utvecklarna och författarna förklarar GPL tydligt
författares skull kräver GPL att modifierade versioner markeras som
har utformat den här versionen av GPL för att förbjuda dessa
...
...

Alternering kan användas för att välja mellan två eller flera alternativ; För att göra detta måste du ange de återstående alternativen i urvalsgruppen, separera var och en med den vertikala strecksymbolen "|".

Kvantifierare

I utökade reguljära uttryck finns det metatecken som anger hur ofta ett tecken upprepas, ungefär som metateckenet "*" indikerar att det föregående tecknet eller strängen med tecken matchar 0 eller fler gånger.

För att matcha ett tecken 0 eller fler gånger kan du använda tecknet "?". Det kommer att göra den tidigare karaktären eller serien av tecken i huvudsak valfri.

I det här exemplet, genom att infoga sekvensen "copy" i den valfria gruppen, visas matchningarna "copyright" och "right":

grep -E "(copy)?right" GPL-3
Copyright (C) 2007 Free Software Foundation, Inc.
För att skydda dina rättigheter måste vi förhindra andra från att neka dig
dessa rättigheter eller ber dig att avstå från rättigheterna. Därför har du
känner till sina rättigheter.
Utvecklare som använder GNU GPL skyddar dina rättigheter med två steg:
(1) hävda upphovsrätten till programvaran och (2) erbjuda dig denna licens
"Upphovsrätt" betyder också upphovsrättsliknande lagar som gäller andra typer av
...
...

Tecknet "+" matchar uttryck 1 eller flera gånger. Det fungerar nästan som "*"-symbolen, men när du använder "+" måste uttrycket matcha minst 1 gång.

Följande uttryck matchar strängen "free" plus 1 eller fler tecken som inte är blanksteg:

grep -E "free[^[:mellanslag:]]+" GPL-3
GNU General Public License är en gratis copyleft-licens för
att ta bort din frihet att dela och förändra verken. Däremot
GNU General Public License är avsedd att garantera din frihet att
När vi talar om fri programvara syftar vi på frihet, inte
ha friheten att distribuera kopior av fri programvara (och ta betalt för

friheter som du fått. Du måste se till att de också tar emot
skydda användarnas frihet att ändra programvaran. Den systematiska
av GPL, efter behov för att skydda användarnas frihet.
patent kan inte användas för att göra programmet icke-fritt.

Antal upprepade matcher

Om du behöver ange hur många gånger matchningar ska upprepas kan du använda hängslen (“( )”). Dessa symboler används för att indikera det exakta antalet, intervallet och övre och nedre gränser för antalet matchningar av ett uttryck.

Om du behöver hitta alla rader som innehåller en kombination av tre vokaler kan du använda följande uttryck:

grep -E "(3)" GPL-3
ändrats, så att deras problem inte felaktigt kommer att hänföras till
författare till tidigare versioner.
ta emot det, i vilket medium som helst, förutsatt att du på ett iögonfallande sätt och
ge enligt föregående stycke, plus en rätt till besittning av
täckt arbete för att samtidigt uppfylla dina skyldigheter enligt detta
Om du behöver hitta alla ord som består av 16-20 tecken, använd följande uttryck:
grep -E "[[:alpha:]](16,20)" GPL-3
vissa skyldigheter om du distribuerar kopior av programvaran, eller om
du ändrar det: ansvar att respektera andras frihet.
c) Förbjuda felaktig framställning av materialets ursprung, eller

Slutsatser

I många fall är kommandot grep användbart för att hitta mönster i filer eller i en hierarki filsystem. Det sparar mycket tid, så det är värt att bekanta dig med dess parametrar och syntax.

Reguljära uttryck är ännu mer mångsidiga och kan användas i många populära program. Till exempel många textredigerare använda reguljära uttryck för att söka och ersätta text.

Dessutom använder avancerade programmeringsspråk reguljära uttryck för att utföra procedurer på specifika datastycken. Att veta hur man arbetar med reguljära uttryck är praktiskt när man löser vanliga datorrelaterade problem.

Taggar: ,

God eftermiddag, gäster!

I dagens artikel vill jag beröra ett så enormt ämne som Vanliga uttryck. Jag tror att alla vet att ämnet regexes (som reguljära uttryck kallas på slang) är enormt inom ramen för ett inlägg. Därför ska jag försöka att kort, men så tydligt som möjligt, samla mina tankar och förmedla dem till dig i .

Låt mig börja med att säga att det finns flera typer av reguljära uttryck:

1. Traditionella reguljära uttryck(de är också grundläggande, grundläggande och grundläggande reguljära uttryck(BRE))

  • Syntaxen för dessa uttryck definieras som föråldrad, men är fortfarande utbredd och används av många UNIX-verktyg
  • Grundläggande reguljära uttryck inkluderar följande metatecken (mer om deras betydelse nedan):
    • \( \) - initial version för ( ) (i utökad)
    • \(\) - initial version för () (i utökad)
    • \n, Var n- nummer från 1 till 9
  • Funktioner för att använda dessa metatecken:
    • En asterisk måste följa uttrycket som motsvarar ett enda tecken. Exempel: *.
    • Uttryck \( blockera\)* bör anses vara felaktig. I vissa fall matchar den noll eller fler upprepningar av strängen blockera. I andra motsvarar det strängen blockera* .
    • Inom en teckenklass ignoreras till stor del specialteckens betydelser. Speciella fall:
    • För att lägga till ett ^-tecken till en uppsättning får det inte placeras först där.
    • För att lägga till ett - tecken till en uppsättning måste det placeras där först eller sist. Till exempel:
      • DNS-namnmall, som kan innehålla bokstäver, siffror, minus och en punkt: [-0-9a-zA-Z.] ;
      • alla tecken utom minus och siffror: [^-0-9] .
    • För att lägga till ett [ eller ] tecken till en uppsättning måste det placeras där först. Till exempel:
      • matchar ], [, a eller b.

2. Avancerade reguljära uttryck(dom är utökade reguljära uttryck(ERE))

  • Syntaxen för dessa uttryck liknar syntaxen för huvuduttrycken, med undantag av:
    • Tog bort användningen av omvända snedstreck för ( ) och () metatecken.
    • Ett snedstreck före en metatecken åsidosätter dess speciella betydelse.
    • Förkastade teoretiskt oregelbunden design\ n .
    • Lade till metatecken + , ? , | .

3. Reguljära uttryck kompatibla med Perl(dom är Perl-kompatibla reguljära uttryck(PCRE))

  • har en rikare och samtidigt förutsägbar syntax än till och med POSIX ERE, så de används ofta av applikationer.

Vanliga uttryck Bestå av mallar, eller snarare ange en mall Sök. Mallen består från regler sökningar, som består av tecken Och metakaraktärer.

Sök regler bestäms av följande operationer:

Uppräkning |

Rör (|) separerar giltiga alternativ, kan man säga - logiskt ELLER. Till exempel "grå|grå" matchar grå eller grå.

Grupp eller förbund()

Runda fästen används för att definiera operatörernas omfattning och företräde. Till exempel är "grå|grå" och "gr(a|e)y" olika mönster, men de beskriver båda en uppsättning som innehåller grå Och grå.

Kvantifiera()? * +

Kvantifierare efter att en karaktär eller grupp bestämmer hur många gånger föregående uttryck kan förekomma.

allmänt uttryck kan upprepningar vara från m till n inklusive.

allmänt uttryck m eller fler repetitioner.

allmänt uttryck inte mer än n repetitioner.

slätn upprepningar.

Frågetecken betyder 0 eller 1 gånger, samma som {0,1} . Till exempel "colou?r" matchar och Färg, Och Färg.

Stjärna betyder 0, 1 eller vilket nummer som helst en gång ( {0,} ). Till exempel "go*gle" matchar ggla, Google, Google och så vidare.

Plus betyder minst 1 en gång ( {1,} ). Till exempel "go+gle" matchar Google, Google etc. (men inte ggla).

Den exakta syntaxen för dessa reguljära uttryck är implementeringsberoende. (det vill säga i grundläggande reguljära uttryck symboler (och)- kom undan med ett snedstreck)

Metakaraktärer, i enkla termer, är symboler som inte motsvarar deras verkliga betydelse, det vill säga en symbol. (prick) är inte en prick, utan vilket tecken som helst, etc. Vänligen bekanta dig med metakaraktärerna och deras betydelser:

. motsvarar ensam någon symbol
[något] Överensstämmer någon singel tecken från de som omges inom parentes. I det här fallet: Tecknet "-" tolkas bokstavligt endast om det finns omedelbart efter en öppning eller före en avslutande parentes: eller [-abc]. Annars anger det ett teckenintervall. Matchar till exempel "a", "b" eller "c". motsvarar små bokstäver i det latinska alfabetet. Dessa beteckningar kan kombineras: matchar a, b, c, q, r, s, t, u, v, w, x, y, z. För att matcha tecknen "[" eller "]" räcker det att avslutande parentes var det första tecknet efter det inledande tecknet: matchar "]", "[", "a" eller "b". Om värdet inom hakparenteser föregås av ett ^-tecken, så matchar uttryckets värde enda tecken bland dessa som inte står inom parentes. Till exempel matchar [^abc] alla andra tecken än "a", "b" eller "c". [^a-z] matchar alla tecken utom gemener i det latinska alfabetet.
^ Matchar början av texten (eller början av valfri rad om läget är rad för rad).
$ Matchar slutet av texten (eller slutet av valfri rad om läget är rad för rad).
\(\) eller () Deklarerar ett "markerat underuttryck" (grupperat uttryck) som kan användas senare (se följande element: \ n). Ett "markerat underuttryck" är också ett "block". Till skillnad från andra operatorer kräver den här (i traditionell syntax) ett omvänt snedstreck, i extended och Perl behövs inte \-tecknet.
\n Var n- detta är ett tal från 1 till 9; motsvarar n det e markerade underuttrycket (till exempel (abcd)\0, det vill säga tecknen abcd är markerade med noll). Denna design är teoretiskt oregelbunden, accepterades det inte i den utökade syntaxen för reguljära uttryck.
*
  • Stjärna efter ett uttryck som matchar ett enstaka tecken, matchar noll eller Mer kopior detta (föregående) uttryck. Till exempel, "*" matchar den tomma strängen, "x", "y", "zx", "zyx" etc.
  • \n*, Var när en siffra från 1 till 9, matchar noll eller fler förekomster att matcha n det markerade underuttrycket. Till exempel, "\(a.\)c\1*" matchar "abcab" och "abcaba", men inte "abcac".

Ett uttryck inneslutet i "\(" och "\)" följt av ett "*" bör betraktas som olagligt. I vissa fall matchar den noll eller fler förekomster av strängen som stod inom parentes. I andra matchar det uttrycket inom parentes, givet "*"-tecknet.

\{x,y\} Motsvarar den sista ( kommande) blockering förekommer åtminstone x och inte mer y en gång. Till exempel, "a\(3,5\)" matchar "aaa", "aaaa" eller "aaaaa". Till skillnad från andra operatörer kräver den här (i traditionell syntax) ett snedstreck.
.* Beteckning av valfritt antal tecken mellan två delar av ett reguljärt uttryck.

Metatecken hjälper oss att använda olika matchningar. Men hur kan vi representera en metatecken som en vanlig karaktär, det vill säga symbolen [ (hakparentes) med betydelsen av en hakparentes? Bara:

  • måste föregås ( skydda) metatecken (. * + \ ? ( )) omvänt snedstreck. Till exempel \. eller \[

För att förenkla definitionen av vissa teckenuppsättningar kombinerades de till den så kallade. klasser och kategorier av karaktärer. POSIX har standardiserat deklarationen av vissa teckenklasser och kategorier, som visas i följande tabell:

POSIX klass liknande beteckning
[:övre:] versaler
[:lägre:] gemener
[:alfa:] versaler och gemener
[:alnum:] siffror, versaler och gemener
[:siffra:] tal
[:xdigit:] hexadecimala siffror
[:punct:] [.,!?:…] punkter
[:tom:] [\t] space och TAB
[:Plats:] [\t\n\r\f\v] hoppa över tecken
[:cntrl:] kontrolltecken
[:Graf:] [^\t\n\r\f\v] sigill symboler
[:skriva ut:] [^\t\n\r\f\v] försegla symboler och hoppa över symboler

I regex finns det något som:

Girighet regex

Jag ska försöka beskriva det så tydligt som möjligt. Låt oss säga att vi vill hitta allt HTML-taggar i någon text. Efter att ha lokaliserat problemet vill vi hitta värdena som finns mellan< и >, tillsammans med samma parenteser. Men vi vet att taggar har olika längd och att det i sig finns minst 50. Att lista dem alla, omsluta dem i metasymboler, är en alltför tidskrävande uppgift. Men vi vet att vi har ett uttryck.* (punktstjärna), som kännetecknar valfritt antal tecken på raden. Genom att använda givet uttryck vi ska försöka hitta i texten (

Så, Hur man skapar RAID-nivå 10/50 på LSI MegaRAID-kontrollern (även relevant för: Intel SRCU42x, Intel SRCS16):

) alla värden mellan< и >. Som ett resultat kommer HELA raden att matcha detta uttryck. varför, eftersom regex är GIRIG och försöker fånga ALLA antal tecken mellan< и >, respektive hela linjen, med start < p>Så... och slut ...> kommer att tillhöra denna regel!

Jag hoppas att detta exempel klargör vad girighet är. För att bli av med denna girighet kan du följa följande väg:

  • ta hänsyn till symbolerna Inte som motsvarar det önskade mönstret (till exempel:<[^>]*> för ovanstående fall)
  • bli av med girighet genom att lägga till en definition av kvantifieraren som icke-girig:
    • *? - "inte girig" ("lat") motsvarighet *
    • +? - “inte girig” (”lat”) motsvarande +
    • (n,)? - "inte girig" ("lat") motsvarighet (n,)
    • .*? - “inte girig” (”lat”) motsvarande.*

Jag skulle vilja lägga till allt ovanstående utökad syntax för reguljära uttryck:

Reguljära uttryck i POSIX liknar traditionell Unix-syntax, men med tillägg av några metatecken:

Plus indikerar att tidigare symbol eller grupp kan upprepas en eller flera gånger. Till skillnad från asterisken krävs minst en upprepning.

Frågetecken gör tidigare symbol eller grupp valfri. Med andra ord, i motsvarande rad det kan vara frånvarande eller närvarande slät ett en gång.

Vertikal stång delar upp alternativa alternativ vanliga uttryck. Ett tecken anger två alternativ, men det kan finnas fler av dem, använd bara fler vertikala streck. Det är viktigt att komma ihåg att denna operator använder så mycket av uttrycket som möjligt. Av denna anledning används den alternativa operatorn oftast inom parentes.

Användningen av snedstreck har också avskaffats: \(…\) blir (...) och \(...\) blir (…).

För att avsluta inlägget kommer jag att ge några exempel på hur man använder regex:

$ katt text1 1 äpple 2 päron 3 banan $ grep p text1 1 äpple 2 päron $ grep "pp*" text1 1 äpple 2 päron $ katt text1 | grep "l\|n" 1 äpple 3 banan $ echo -e "hitta en\n* här" | grep "\*" * här $ grep "pl\?.*r" text1 # p, på rader där det finns ett r 2 päron $ grep "a.." text1 # rader med ett a följt av minst 2 tecken 1 apple 3 banana $ grep "" text1 # sök efter rader som innehåller 3 eller p 1 äpple 2 päron 3 banan $ echo -e "hitta en\n* här\nnågonstans." | grep "[.*]" * här någonstans..namn]$ echo -e "123\n456\n789\n0" | grep "" 123,456,789 $ sed -e "/\(a.*a\)\|\(s.*p\)/s/a/A/g" text1 # ersätt a med A på alla rader där efter a kommer a eller efter p kommer p 1 Äpple 2 päron 3 bAnAnA *\./ SISTA ORD./g" Först. ETT SISTA ORD. Detta är ett SISTA ORD.

Med vänlig hälsning, McSim!

grep står för 'global regular expression printer'. grep skär linjerna du behöver från textfiler som innehåller användarspecificerad text.

grep kan användas på två sätt - på egen hand eller i kombination med strömmar.

grep är mycket omfattande i funktionalitet på grund av det stora antalet alternativ som det stöder, såsom: sökning med hjälp av ett strängmönster eller RegExp reguljära uttrycksmönster eller perlbaserade reguljära uttryck, etc.

På grund av dess olika funktionalitet grep-verktyget har många alternativ inklusive egrep (Utökad GREP), fgrep (fast GREP), pgrep (Process GREP), rgrep (rekursiv GREP) etc. Men dessa alternativ har mindre skillnader från den ursprungliga grep.

grep-alternativ

$ grep -V grep (GNU grep) 2.10 Copyright (C) 2011 Free Software Foundation, Inc. Licens GPLv3+

Det finns modifieringar av grep-verktyget: egrep (med utökad bearbetning av reguljära uttryck), fgrep (som behandlar $*^|()\-symboler som bokstavliga, d.v.s. bokstavligen), rgrep (med rekursiv sökning aktiverad).

    egrep är samma som grep -E

    fgrep är samma som grep -F

    rgrep är samma som grep -r

    grep [-b] [-c] [-i] [-l] [-n] [-s] [-v] restricted_regex_BRE [fil ...]

Kommandot grep matchar rader i källfiler mot mönstret som specificeras av limited_regex. Om inga filer anges används standardinmatning. Vanligtvis kopieras varje framgångsrikt matchad sträng till standardutdata; om det finns flera källfiler ges filnamnet före den hittade raden. grep använder en kompakt, icke-deterministisk algoritm. Begränsade reguljära uttryck (uttryck som har teckensträngar med sina betydelser och använder en begränsad uppsättning alfanumeriska och specialtecken) uppfattas som mallar. De har samma betydelse som reguljära uttryck i ed.

För att undvika tecknen $, *, , ^, |, () och \ från skaltolkningen är det enklast att omsluta constrained_regex i enkla citattecken.

Alternativ:

B Inför varje rad med blocknumret där den hittades. Detta kan vara användbart när du söker efter block efter kontext (block numreras från 0). -c Skriver endast ut antalet rader som innehåller mönstret. -h Förhindrar att filnamnet som innehåller den matchade raden skrivs ut före själva raden. Används vid sökning i flera filer. -I ignorerar skiftläge när man gör jämförelser. -l Skriver endast ut namnen på filerna som innehåller de matchande strängarna, en per rad. Om ett mönster hittas på flera rader i en fil, upprepas inte filnamnet. -n Skriver ut före varje rad dess nummer i filen (raderna är numrerade från 1). -s Undertrycker meddelanden om obefintliga eller oläsbara filer. -v Skriver ut alla rader utom de som innehåller ett mönster. -w Söker efter uttrycket som ett ord, som om det var omgivet av metatecken \< и \>.

grep --hjälp

Användning: grep [OPTION]... PATTERN [FILE]... Söker efter PATTERN i varje FILE eller standardingång. Som standard är PATTERN ett enkelt reguljärt uttryck (BRE). Exempel: grep -i "hej världen" menu.h main.c Välja typ av reguljärt uttryck och dess tolkning: -E, --extended-regexp PATTERN - utökat reguljärt uttryck (ERE) -F, --fixed-regexp PATTERN - strängar fast längd, åtskilda av nyrader -G, --basic-regexp PATTERN - enkelt reguljärt uttryck (BRE) -P, --perl-regexp PATTERN - Perl reguljära uttryck -e, --regexp=PATTERN använd PATTERN för att söka - f, --file=FIL ta PATTERN från FILE -i, --ignore-case ignore case difference -w, --word-regexp PATTERN måste matcha alla ord -x, --line-regexp PATTERN måste matcha hela raden -z , --null-datarader separeras av en nollbyte snarare än ett radsluttecken Övrigt: -s, --no-meddelanden undertrycker felmeddelanden -v, --revert-match välj omatchade rader -V, - -version print versionsinformation och avsluta --hjälp visa denna hjälp och avsluta --mmap för bakåtkompatibilitet, ignorerad Utdatakontroll: -m, --max-count=NUMBER stopp efter det angivna ANTAL matchningar -b, --byte-offset skriv ut byteoffset tillsammans med utgångsraderna -n, --line-number skriv ut raden nummer tillsammans med utdataraderna --line-buffrad spola bufferten efter varje rad -H, --with-filename skriv ut filnamnet för varje matchning -h, --no-filename starta inte utdata med filnamnet -- label=LABEL använd LABEL som filnamn för standardinmatning -o, --only-matching visar bara en del av raden som matchar PATTERN -q, --quiet, --silent undertrycka all normal utdata --binary-files=TYPE anta den där binär fil har en TYP: binär, text eller utan matchning. -a, --text samma som --binary-files=text -I samma som --binary-files=without-match -d, --directories=ACTION hur man hanterar kataloger ACTION kan läsas ), recurse (rekursivt) eller hoppa över (hoppa över). -D, --devices=ACTION hur man hanterar enheter, FIFOs och sockets ACTION kan läsas eller hoppa över -R, -r, --recursive samma som --directorys=recurse --include=F_PATTERN bearbetar endast filer som matchar under F_MALL - -exclude=F_TEMPLATE hoppa över filer och kataloger som matchar F_TEMPLATE --exclude-from=FILE hoppa över filer som matchar mallfilerna från FILE --exclude-dir=MALL-kataloger som matchar PATTERN kommer att hoppas över -L, - -files-without-match print only FILnamn utan matchningar -l, --files-with-matches skriv endast ut FILnamn med matchningar -c, --count skriv endast ut antalet matchande rader per FIL -T, --initial-tab align tab (om nödvändigt) - Z, --null print byte 0 efter FILnamnet Kontexthantering: -B, --before-context=NUM skriv ut ANTAL rader i föregående sammanhang -A, --after-context=NUM skriv ut ANTAL rader av den efterföljande kontexten -C, --context[=NUMBER] skriv ut ANTAL kontextrader -NUMBER är samma som --context=NUMBER --color[=WHEN], --colour[=WHEN] använd markörer för att särskilja matchning rader; WHEN kan vara alltid, aldrig eller auto -U, --binary, ta inte bort CR-tecken i slutet av raden (MSDOS) -u, --unix-byte-offsets visar offset som om det inte fanns några CR-s (MSDOS) ) Istället för "egrep" är det tänkt att den ska köra "grep -E". "grep -F" antas istället för "fgrep". Det är bättre att inte köra som "egrep" eller "fgrep". När FILE inte anges, eller när FILE är -, läses standardinmatningen. Om färre än två filer anges, antas -h. Om en matchning hittas kommer utgångskoden att vara 0 och 1 om inte. Om fel uppstår, eller om alternativet -q inte är specificerat, blir utgångskoden 2. Rapportera fel till: Vänligen rapportera fel i översättningen till: GNU Greps hemsida: Hjälp för att arbeta med GNU-program: