Reguliere expressies in bash. Bash Reguliere Expressies: Handleiding voor het maken, Toepassingen, Voorbeelden. Punt om elk teken weer te geven

Reguliere expressies zijn een zeer krachtig hulpmiddel voor het matchen, verwerken en wijzigen van tekenreeksen die kunnen worden gebruikt om een ​​verscheidenheid aan problemen op te lossen. Dit zijn de belangrijkste:

  • Tekstinvoer controleren;
  • Zoek en vervang tekst in een bestand;
  • Batch hernoemen van bestanden;
  • Interactie met diensten zoals Apache;
  • Een string vergelijken met een patroon.

Dit is geen volledige lijst, met reguliere expressies kun je veel meer doen. Maar voor nieuwe gebruikers lijken ze misschien te ingewikkeld, omdat een speciale taal wordt gebruikt om ze te vormen. Maar gezien de kracht die het biedt, zou elke systeembeheerder de reguliere Linux-expressies moeten kennen en kunnen gebruiken.

In dit artikel gaan we bash-reguliere expressies voor beginners behandelen, zodat je alle functies van deze tool kunt begrijpen.

Er kunnen twee soorten tekens worden gebruikt in reguliere expressies:

  • gewone brieven;
  • metakarakters.

Reguliere tekens zijn letters, cijfers en leestekens waaruit een tekenreeks bestaat. Alle teksten zijn opgebouwd uit letters en je kunt ze gebruiken in reguliere expressies om de gewenste positie in de tekst te vinden.

Metatekens zijn iets anders, ze geven kracht aan reguliere expressies. Met metatekens kun je veel meer doen dan alleen maar naar één teken zoeken. U kunt zoeken naar tekencombinaties, een dynamisch aantal tekens gebruiken en bereiken selecteren. Alle speciale tekens zijn onder te verdelen in twee typen, dit zijn vervangende tekens die gewone tekens vervangen, of operators die aangeven hoe vaak een teken herhaald mag worden. De syntaxis voor een reguliere expressie ziet er als volgt uit:

regulier_symbool speciaal teken_operator

wildcard_replacement speciaal teken_operator

  • - letterlijke speciale tekens beginnen met een backslash en worden ook gebruikt als u een speciaal teken in de vorm van een leesteken moet gebruiken;
  • ^ - geeft het begin van de regel aan;
  • $ - geeft het einde van de regel aan;
  • * - geeft aan dat het vorige teken 0 of meer keer kan worden herhaald;
  • + - geeft aan dat het vorige teken meer dan één of meerdere keren moet worden herhaald;
  • ? - het vorige teken kan nul of één keer voorkomen;
  • (N)- geeft aan hoe vaak (n) u het vorige teken moet herhalen;
  • (n,n)- het vorige teken kan van N tot n keer worden herhaald;
  • . - elk teken behalve regelinvoer;
  • — elk teken gespecificeerd tussen haakjes;
  • x|y— symbool x of symbool y;
  • [^az]- elk teken, behalve de tekens die tussen haakjes zijn aangegeven;
  • — elk teken uit het opgegeven bereik;
  • [^a-z]- elk teken dat niet in het bereik is;
  • B— geeft een woordgrens aan met een spatie;
  • B- geeft aan dat het teken binnen een woord moet staan, bijvoorbeeld, ux zal overeenkomen met uxb of smoking, maar zal niet overeenkomen met Linux;
  • D- betekent dat het teken een cijfer is;
  • D- niet-cijferig karakter;
  • N— regelinvoerteken;
  • s- een van de spatietekens, spatie, tab, enzovoort;
  • S- elk ander teken dan een spatie;
  • t- tabteken;
  • v— verticaal tabteken;
  • met wie— elk alfabetisch teken, inclusief onderstrepingsteken;
  • W- elk alfabetisch teken, behalve onderstrepingstekens;
  • uXXX- Unicdo-symbool.

Het is belangrijk op te merken dat er vóór letterlijke speciale tekens een schuine streep moet worden gebruikt om aan te geven dat het speciale teken volgt. Het omgekeerde is ook waar, als je een speciaal teken zonder schuine streep als normaal teken wilt gebruiken, dan moet je een schuine streep toevoegen.

U wilt bijvoorbeeld de tekenreeks 1+ 2=3 in de tekst vinden. Als je deze string als reguliere expressie gebruikt, zul je niets vinden, omdat het systeem de plus interpreteert als een speciaal teken dat zegt dat de vorige een of meerdere keren moet worden herhaald. Er moet dus een escape-teken voor zijn: 1 + 2 = 3. Zonder escape-tekens zou onze reguliere expressie alleen overeenkomen met de tekenreeks 11=3 of 111=3 enzovoort. U hoeft geen streepje voor de gelijken te plaatsen, omdat het geen speciaal teken is.

Voorbeelden van reguliere expressies

Nu we de basis hebben behandeld en je weet hoe alles werkt, blijft het om de opgedane kennis over reguliere linux grep-expressies in de praktijk te consolideren. Twee zeer nuttige speciale tekens zijn ^ en $, die het begin en einde van een regel aangeven. We willen bijvoorbeeld alle gebruikers in ons systeem laten registreren waarvan de naam begint met een s. Dan kun je de reguliere expressie gebruiken "^s". U kunt het egrep-commando gebruiken:

egrep "^s" /etc/passwd

Als we regels willen selecteren op het laatste teken in de regel, kunnen we $ gebruiken. Laten we bijvoorbeeld alle systeemgebruikers selecteren, zonder shell, records over dergelijke gebruikers eindigen op false:

egrep "false$" /etc/passwd

Gebruik deze uitdrukking om gebruikersnamen die beginnen met s of d weer te geven:

egrep "^" /etc/passwd

Hetzelfde resultaat kan worden verkregen door het symbool "|" te gebruiken. De eerste optie is meer geschikt voor reeksen, en de tweede wordt vaker gebruikt voor gewoon of/of:

egrep "^" /etc/passwd

Laten we nu alle gebruikers selecteren wiens naam niet drie tekens lang is. De gebruikersnaam eindigt met een dubbele punt. We kunnen zeggen dat het elk alfabetisch teken kan bevatten, dat drie keer moet worden herhaald vóór de dubbele punt:

egrep "^w(3):" /etc/passwd

conclusies

In dit artikel hebben we de reguliere Linux-expressies behandeld, maar dat was slechts de basis. Als je wat dieper graaft, zul je merken dat je veel interessantere dingen kunt doen met deze tool. De tijd besteed aan het leren van reguliere expressies zal zeker de moeite waard zijn.

Aan het einde van de lezing van Yandex over reguliere expressies:

Om teksten in bash-scripts volledig te verwerken met sed en awk, hoef je alleen reguliere expressies te begrijpen. Implementaties van deze meest bruikbare tool zijn letterlijk overal te vinden, en hoewel alle reguliere expressies op een vergelijkbare manier zijn gerangschikt, gebaseerd op dezelfde ideeën, heeft het werken ermee bepaalde functies in verschillende omgevingen. Hier zullen we het hebben over reguliere expressies die geschikt zijn voor gebruik in Linux-opdrachtregelscripts.

Dit materiaal is bedoeld als een introductie tot reguliere expressies voor degenen die misschien niet weten wat reguliere expressies zijn. Laten we daarom bij het begin beginnen.

Wat zijn reguliere expressies?

Voor velen, wanneer ze voor het eerst reguliere expressies zien, komt meteen de gedachte op dat ze een nietszeggende wirwar van karakters voor zich hebben. Maar dit is natuurlijk verre van het geval. Kijk bijvoorbeeld eens naar deze regex


Naar onze mening zal zelfs een absolute beginner meteen begrijpen hoe het werkt en waarom je het nodig hebt :) Als je het niet helemaal begrijpt, lees dan gewoon verder en alles valt op zijn plaats.
Een reguliere expressie is een patroon dat programma's zoals sed of awk gebruiken om tekst te filteren. Sjablonen gebruiken gewone ASCII-tekens die zichzelf voorstellen, en zogenaamde metatekens die bijvoorbeeld een speciale rol spelen, waardoor je naar bepaalde groepen tekens kunt verwijzen.

Typen reguliere expressies

Implementaties van reguliere expressies in verschillende omgevingen, bijvoorbeeld in programmeertalen als Java, Perl en Python, in Linux-tools als sed, awk en grep, hebben bepaalde eigenaardigheden. Deze functies zijn afhankelijk van de zogenaamde reguliere expressieverwerkingsengines, die zich bezighouden met de interpretatie van patronen.
Linux heeft twee reguliere expressie-engines:
  • Een engine die de POSIX Basic Regular Expression (BRE)-standaard ondersteunt.
  • Een engine die de POSIX Extended Regular Expression (ERE)-standaard ondersteunt.
De meeste Linux-hulpprogramma's voldoen aan ten minste de POSIX BRE-standaard, maar sommige hulpprogramma's (inclusief sed) begrijpen slechts een subset van de BRE-standaard. Een van de redenen voor deze beperking is de wens om dergelijke hulpprogramma's zo snel mogelijk te maken in tekstverwerking.

De POSIX ERE-standaard wordt vaak geïmplementeerd in programmeertalen. Het stelt je in staat om veel tools te gebruiken bij het ontwikkelen van reguliere expressies. Dit kunnen bijvoorbeeld speciale tekenreeksen zijn voor veelgebruikte patronen, zoals het zoeken naar afzonderlijke woorden of reeksen getallen in de tekst. Awk ondersteunt de ERE-standaard.

Er zijn veel manieren om reguliere expressies te ontwikkelen, afhankelijk van de mening van de programmeur en van de kenmerken van de engine waaronder ze zijn gemaakt. Het is niet eenvoudig om generieke reguliere expressies te schrijven die elke engine kan begrijpen. Daarom zullen we ons concentreren op de meest gebruikte reguliere expressies en kijken naar de specifieke kenmerken van hun implementatie voor sed en awk.

POSIX BRE reguliere expressies

Misschien is het eenvoudigste BRE-patroon een reguliere expressie voor het vinden van een exacte overeenkomst van een reeks tekens in tekst. Zo ziet het zoeken naar een string in sed en awk eruit:

$ echo "Dit is een test" | sed -n "/test/p" $ echo "Dit is een test" | awk "/test/(druk $0 af)"

Tekst zoeken op patroon in sed


Tekst zoeken op patroon in awk

U zult merken dat het zoeken naar een bepaald patroon wordt uitgevoerd zonder rekening te houden met de exacte locatie van de tekst in de tekenreeks. Daarnaast maakt het aantal voorvallen niet uit. Nadat de reguliere expressie de gegeven tekst ergens in de tekenreeks heeft gevonden, wordt de tekenreeks als geschikt beschouwd en doorgegeven voor verdere verwerking.

Houd er bij het werken met reguliere expressies rekening mee dat ze hoofdlettergevoelig zijn:

$ echo "Dit is een test" | awk "/Test/(print $0)" $ echo "Dit is een test" | awk "/test/(druk $0 af)"

Reguliere expressies zijn hoofdlettergevoelig

De eerste reguliere expressie vond geen overeenkomsten, aangezien het woord "test", dat met een hoofdletter begint, niet in de tekst voorkomt. De tweede, geconfigureerd om te zoeken naar een woord dat in hoofdletters is geschreven, vond een geschikte string in de stream.

In reguliere expressies kunt u niet alleen letters gebruiken, maar ook spaties en cijfers:

$ echo "Dit is weer een test 2" | awk "/test 2/(druk $0 af)"

Een stuk tekst zoeken dat spaties en cijfers bevat

Spaties worden door de engine voor reguliere expressies behandeld als gewone tekens.

Speciale symbolen

Bij het gebruik van verschillende tekens in reguliere expressies, zijn er een paar dingen om in gedachten te houden. Er zijn bijvoorbeeld enkele speciale tekens of metatekens die een speciale benadering vereisen wanneer ze in een sjabloon worden gebruikt. Daar zijn ze:

.*^${}\+?|()
Als een van deze nodig is in het patroon, moet deze worden geëscaped met een backslash (backslash) - \ .

Als u bijvoorbeeld een dollarteken in de tekst moet vinden, moet dit in de sjabloon worden opgenomen, voorafgegaan door een escape-teken. Laten we zeggen dat er een bestand mijnbestand is met de volgende tekst:

Er staat 10$ op mijn zak
Het dollarteken kan worden gedetecteerd met een patroon als dit:

$ awk "/\$/(print $0)" mijnbestand

Een speciaal teken in een sjabloon gebruiken

Bovendien is de backslash ook een speciaal teken, dus als je hem in een sjabloon wilt gebruiken, moet je er ook aan ontsnappen. Het ziet eruit als twee schuine strepen die elkaar opvolgen:

$ echo "\ is een speciaal teken" | awk "/\\/(druk $0 af)"

Backslash ontsnapt

Hoewel de slash niet in de bovenstaande lijst met speciale tekens staat, zal een poging om deze te gebruiken in een reguliere expressie die is geschreven voor sed of awk, resulteren in een fout:

$ echo "3 / 2" | awk "///(druk $0 af)"

Onjuist gebruik van een schuine streep in een sjabloon

Als het nodig is, moet het ook worden ontsnapt:

$ echo "3 / 2" | awk "/\//(druk $0 af)"

Ontsnappen aan een schuine streep

Ankersymbolen

Er zijn twee speciale tekens om een ​​patroon aan het begin of einde van een tekstreeks te verankeren. Met het hoofdlettersymbool - ^ kunt u reeksen tekens beschrijven die aan het begin van tekstregels staan. Als het patroon dat u zoekt ergens anders in de tekenreeks voorkomt, zal de reguliere expressie er niet op reageren. Het gebruik van dit symbool ziet er als volgt uit:

$ echo "welkom op de likegeeks-website" | awk "/^likegeeks/(print $0)" $ echo "likegeeks website" | awk "/^likegeeks/(print $0)"

Zoek een patroon aan het begin van een string

Het ^-symbool is ontworpen om te zoeken naar een patroon aan het begin van een regel, terwijl er ook rekening wordt gehouden met hoofdletters. Laten we eens kijken hoe dit de verwerking van een tekstbestand zal beïnvloeden:

$ awk "/^this/(print $0)" mijnbestand


Zoek naar een patroon aan het begin van een regel in tekst uit een bestand

Als u bij het gebruik van sed een escape ergens in een patroon plaatst, wordt deze behandeld als elk ander normaal teken:

$ echo "Deze ^ is een test" | sed -n "/s ^/p"

Kap niet aan begin patroon in sed

In awk, wanneer hetzelfde patroon wordt gebruikt, moet het gegeven teken worden geëscaped:

$ echo "Deze ^ is een test" | awk "/s \^/(druk $0 af)"

Een deksel niet aan het begin van een patroon in awk

Met het zoeken naar tekstfragmenten aan het begin van de regel kwamen we erachter. Wat als u iets aan het einde van een regel moet vinden?

Het dollarteken - $ , het ankerteken voor het einde van de regel, helpt ons hierbij:

$ echo "Dit is een test" | awk "/test$/(druk $0 af)"

Tekst zoeken aan het einde van een regel

Beide ankertekens kunnen in hetzelfde patroon worden gebruikt. Laten we het bestand myfile verwerken, waarvan de inhoud wordt weergegeven in de onderstaande afbeelding, met behulp van de volgende reguliere expressie:

$ awk "/^dit is een test$/(print $0)" mijnbestand


Een patroon dat speciale tekens gebruikt voor het begin en einde van een string

Zoals u kunt zien, reageerde de sjabloon alleen op een tekenreeks die volledig overeenkwam met de gegeven reeks tekens en hun locatie.

Ga als volgt te werk om lege regels uit te filteren met ankertekens:

$ awk "!/^$/(print $0)" mijnbestand
In deze sjabloon heb ik het ontkenningssymbool, het uitroepteken -! . Met dit patroon wordt gezocht naar lijnen die niets bevatten tussen het begin en het einde van de regel, en dankzij het uitroepteken worden alleen lijnen afgedrukt die niet overeenkomen met dit patroon.

Punt symbool

De punt wordt gebruikt om naar elk afzonderlijk teken te zoeken, behalve het teken voor de nieuwe regel. Laten we het bestand mijnbestand doorgeven aan zo'n reguliere expressie, waarvan de inhoud hieronder wordt gegeven:

$ awk "/.st/(print $0)" mijnbestand


Punt gebruiken in reguliere expressies

Zoals te zien is in de uitvoer, komen alleen de eerste twee regels van het bestand overeen met het patroon, omdat ze de reeks tekens "st" bevatten, voorafgegaan door een ander teken, terwijl de derde regel geen geschikte reeks bevat, en de vierde regel doet, maar het staat helemaal aan het begin van de regel.

Karakter klassen

Een punt komt overeen met elk afzonderlijk teken, maar wat als u de reeks tekens die u zoekt flexibeler wilt beperken? In een dergelijke situatie kunt u tekenklassen gebruiken.

Dankzij deze aanpak kun je een zoekopdracht organiseren voor elk personage uit een bepaalde set. Om een ​​tekenklasse te beschrijven, worden vierkante haken - gebruikt:

$ awk "/th/(print $0)" mijnbestand


Beschrijving van een tekenklasse in een reguliere expressie

Hier zoeken we naar een reeks tekens "th" voorafgegaan door het teken "o" of het teken "i".

Klassen zijn handig bij het zoeken naar woorden die kunnen beginnen met een hoofdletter of een kleine letter:

$ echo "dit is een test" | awk "/his is een test/(print $0)" $ echo "Dit is een test" | awk "/his is een test/(print $0)"

Zoek naar woorden die kunnen beginnen met een kleine letter of een hoofdletter

Karakterklassen zijn niet beperkt tot letters. Hier kunnen ook andere karakters worden gebruikt. Het is onmogelijk om van tevoren te zeggen in welke situatie de lessen nodig zullen zijn - het hangt allemaal af van het probleem dat wordt opgelost.

Karakterklassen negeren

Symboolklassen kunnen ook worden gebruikt om het hierboven beschreven omgekeerde probleem op te lossen. In plaats van te zoeken naar symbolen die in de klas zijn opgenomen, kunt u namelijk een zoekopdracht organiseren voor alles wat niet in de klas is opgenomen. Om dit gedrag van een reguliere expressie te bereiken, moet u een ^-teken voor de lijst met klassetekens plaatsen. Het ziet er zo uit:

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


Zoeken naar tekens die niet in een klas zitten

In dit geval worden reeksen tekens "th" gevonden, waarvoor geen "o" of "i" staat.

Tekenreeksen

In tekenklassen kun je reeksen tekens beschrijven met streepjes:

$ awk "/st/(print $0)" mijnbestand


Een reeks tekens in een tekenklasse beschrijven

In dit voorbeeld komt de reguliere expressie overeen met de tekenreeks "st" voorafgegaan door een willekeurig teken dat zich in alfabetische volgorde tussen de tekens "e" en "p" bevindt.

Bereiken kunnen ook worden gemaakt op basis van getallen:

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

Reguliere expressie voor het vinden van drie willekeurige getallen

Een tekenklasse kan meerdere bereiken bevatten:

$ awk "/st/(print $0)" mijnbestand


Karakterklasse bestaande uit meerdere bereiken

Deze reguliere expressie komt overeen met alle reeksen van "st" voorafgegaan door tekens uit de bereiken a-f en m-z .

Speciale karakterklassen

BRE heeft speciale tekenklassen die kunnen worden gebruikt bij het schrijven van reguliere expressies:
  • [[:alpha:]] - komt overeen met elk alfabetisch teken dat in hoofdletters of kleine letters is geschreven.
  • [[:alnum:]] - komt overeen met elk alfanumeriek teken, namelijk tekens in het bereik 0-9 , A-Z , a-z .
  • [[:blank:]] - Komt overeen met een spatie en een tab.
  • [[:digit:]] - elk numeriek teken van 0 tot 9 .
  • [[:upper:]] - alfabetische hoofdletters - A-Z .
  • [[:lower:]] - alfabetische tekens in kleine letters - a-z .
  • [[:print:]] - komt overeen met elk afdrukbaar teken.
  • [[:punct:]] - komt overeen met leestekens.
  • [[:spatie:]] - spatietekens, in het bijzonder - spatie, tab, tekens NL , FF , VT , CR .
U kunt speciale klassen gebruiken in sjablonen zoals deze:

$ echo "abc" | awk "/[[:alpha:]]/(print $0)" $ echo "abc" | awk "/[[:digit:]]/(print $0)" $ echo "abc123" | awk "/[[:cijfer:]]/(druk $0 af)"


Speciale tekenklassen in reguliere expressies

Asterisk symbool

Als u een asterisk achter een teken in een patroon plaatst, betekent dit dat de reguliere expressie werkt als het teken een willekeurig aantal keren in de tekenreeks voorkomt - inclusief de situatie waarin het teken afwezig is in de tekenreeks.

$ echo "test" | awk "/tes*t/(print $0)" $ echo "tessst" | awk "/tes*t/(druk $0 af)"


Het *-teken gebruiken in reguliere expressies

Dit jokerteken wordt meestal gebruikt om te werken met woorden die altijd verkeerd gespeld zijn, of voor woorden die anders gespeld kunnen worden:

$ echo "Ik hou van groene kleur" | awk "/colou*r/(print $0)" $ echo "Ik hou van groene kleur" | awk "/colou*r/(print $0)"

Een woord zoeken met verschillende spellingen

In dit voorbeeld komt dezelfde reguliere expressie overeen met zowel het woord "kleur" als het woord "kleur". Dit komt doordat het teken "u", gevolgd door een asterisk, afwezig kan zijn of meerdere keren achter elkaar kan voorkomen.

Een andere handige functie die voortkomt uit het sterretje, is om het te combineren met een punt. Door deze combinatie kan de reguliere expressie reageren op een willekeurig aantal tekens:

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


Sjabloon die reageert op een willekeurig aantal tekens

In dit geval maakt het niet uit hoeveel en welke tekens tussen de woorden "this" en "test" staan.

De asterisk kan ook worden gebruikt met tekenklassen:

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


Het sterretje gebruiken met tekenklassen

In alle drie de voorbeelden werkt de reguliere expressie omdat de asterisk na de tekenklasse betekent dat als een willekeurig aantal "a"- of "e"-tekens wordt gevonden, of als ze niet worden gevonden, de tekenreeks overeenkomt met het gegeven patroon.

POSIX ERE reguliere expressies

De POSIX ERE-sjablonen die door sommige Linux-hulpprogramma's worden ondersteund, kunnen extra tekens bevatten. Zoals eerder vermeld ondersteunt awk deze standaard, maar sed niet.

Hier zullen we kijken naar de meest gebruikte karakters in ERE-patronen, die handig voor u zullen zijn bij het maken van uw eigen reguliere expressies.

▍Vraagteken

Het vraagteken geeft aan dat het voorgaande teken één keer of helemaal niet in de tekst kan voorkomen. Dit karakter is een van de herhalingsmetakarakters. Hier zijn enkele voorbeelden:

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


Vraagteken in reguliere expressies

Zoals u kunt zien, komt de letter "s" in het derde geval twee keer voor, dus de reguliere expressie reageert niet op het woord "testst".

Het vraagteken kan ook worden gebruikt met tekenklassen:

$ 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 "teest" | awk "/t?st/(druk $0 af)"


Vraagteken- en tekenklassen

Als er geen karakters uit de klasse in de string voorkomen, of één ervan komt één keer voor, dan werkt de reguliere expressie, maar zodra er twee karakters in het woord verschijnen, vindt het systeem geen match meer voor het patroon in de tekst.

▍Plus-symbool

Het plusteken in het patroon geeft aan dat de reguliere expressie overeenkomt met de overeenkomst als het voorgaande teken een of meer keren in de tekst voorkomt. Tegelijkertijd zal een dergelijke constructie niet reageren op de afwezigheid van een symbool:

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


Plusteken in reguliere expressies

Als er in dit voorbeeld geen "e"-teken in het woord staat, zal de engine voor reguliere expressies geen overeenkomsten in de tekst vinden. Het plus-symbool werkt ook met tekenklassen - op deze manier is het vergelijkbaar met het sterretje en het vraagteken:

$ 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/(druk $0 af)"


Plusteken- en karakterklassen

In dit geval, als de tekenreeks een teken uit de klasse bevat, wordt aangenomen dat de tekst overeenkomt met het patroon.

▍ Krullende beugels

De accolades die in ERE-patronen kunnen worden gebruikt, zijn vergelijkbaar met de hierboven besproken tekens, maar ze stellen u in staat om nauwkeuriger het vereiste aantal voorkomens van het teken dat eraan voorafgaat te specificeren. U kunt een limiet in twee formaten opgeven:
  • n - een getal dat het exacte aantal gezochte voorvallen aangeeft
  • n, m - twee getallen die als volgt worden geïnterpreteerd: "ten minste n keer, maar niet meer dan m".
Hier zijn voorbeelden van de eerste optie:

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

Krullende accolades in patronen, het exacte aantal keren vinden

In oudere versies van awk moest je de --re-interval command-line switch gebruiken om het programma intervallen in reguliere expressies te laten herkennen, maar in nieuwere versies niet.

$ 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)"


Afstand tussen accolades

In dit voorbeeld moet het teken "e" 1 of 2 keer voorkomen in de string, dan zal de reguliere expressie reageren op de tekst.

Krullende accolades kunnen ook worden gebruikt met tekenklassen. De voor u al bekende principes zijn hier van toepassing:

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


Krullende accolades en karakterklassen

De sjabloon reageert op de tekst als het teken "a" of het teken "e" een of twee keer voorkomt.

▍Logisch "of" symbool

Symbool | - een verticale balk, betekent een logische "of" in reguliere expressies. Bij het verwerken van een reguliere expressie die meerdere fragmenten bevat, gescheiden door een dergelijk teken, zal de engine de geparseerde tekst als een overeenkomst beschouwen als deze overeenkomt met een van de fragmenten. Hier is een voorbeeld:

$ echo "Dit is een test" | awk "/test|exam/(print $0)" $ echo "Dit is een examen" | awk "/test|exam/(print $0)" $ echo "Dit is iets anders" | awk "/test|examen/(druk $0 af)"


Booleaanse "of" in reguliere expressies

In dit voorbeeld is de reguliere expressie geconfigureerd om te zoeken naar de woorden "test" of "exam" in de tekst. Let op het feit dat tussen de sjabloonfragmenten en het |-symbool dat ze scheidt. er mogen geen spaties zijn.

Reguliere expressiefragmenten kunnen worden gegroepeerd met haakjes. Als u een bepaalde reeks tekens groepeert, wordt deze door het systeem als een normaal teken waargenomen. Dat wil zeggen dat er bijvoorbeeld herhalingsmetatekens op kunnen worden toegepast. Hier is hoe het eruit ziet:

$ echo "Vind ik leuk" | awk "/Like(Geeks)?/(print $0)" $ echo "LikeGeeks" | awk "/Like(Geeks)?/(print $0)"


Fragmenten van reguliere expressies groeperen

In deze voorbeelden staat het woord "Geeks" tussen haakjes, gevolgd door een vraagteken. Bedenk dat het vraagteken "0 of 1 herhaling" betekent, met als resultaat dat de reguliere expressie overeenkomt met zowel de tekenreeks "Vind ik leuk" als de tekenreeks "LikeGeeks".

Praktijkvoorbeelden

Nu we de basis van reguliere expressies hebben behandeld, is het tijd om er iets nuttigs mee te doen.

▍Het aantal bestanden tellen

Laten we een bash-script schrijven dat bestanden telt die zich in mappen bevinden die naar de omgevingsvariabele PATH zijn geschreven. Om dit te doen, moet u eerst een lijst met paden naar mappen maken. Laten we dit doen met sed en dubbele punten vervangen door spaties:

$ echo $PATH | sed "s/:/ /g"
De opdracht Replace ondersteunt reguliere expressies als patronen voor het zoeken naar tekst. In dit geval is alles uiterst eenvoudig, we zijn op zoek naar een dubbele punt, maar niemand neemt de moeite om hier iets anders te gebruiken - het hangt allemaal af van de specifieke taak.
Nu moeten we de resulterende lijst in een lus doorlopen en de nodige acties uitvoeren om het aantal bestanden daar te tellen. Het algemene schema van het script is als volgt:

Mypath=$(echo $PATH | sed "s/:/ /g") voor directory in $mypath do done
Laten we nu de volledige tekst van het script schrijven, met behulp van de opdracht ls om informatie te krijgen over het aantal bestanden in elk van de mappen:

#!/bin/bash mypath=$(echo $PATH | sed "s/:/ /g") count=0 voor directory in $mypath do check=$(ls $directory) voor item in $check do count=$ [ $count + 1 ] done echo "$directory - $count" count=0 klaar
Bij het uitvoeren van het script kan blijken dat sommige mappen van PATH niet bestaan, maar dit belet niet dat bestanden in bestaande mappen worden geteld.


Aantal bestanden

De belangrijkste waarde van dit voorbeeld is dat je met dezelfde aanpak veel complexere problemen kunt oplossen. Welke hangt af van uw behoeften.

▍E-mailadressen verifiëren

Er zijn websites met enorme verzamelingen reguliere expressies waarmee u e-mailadressen, telefoonnummers, enzovoort kunt controleren. Het is echter één ding om kant-en-klaar te nemen, en iets heel anders om zelf iets te creëren. Laten we dus een reguliere expressie schrijven om e-mailadressen te valideren. Laten we beginnen met de analyse van de initiële gegevens. Hier is bijvoorbeeld een adres:

[e-mail beveiligd]
De gebruikersnaam, gebruikersnaam , kan bestaan ​​uit alfanumerieke tekens en enkele andere tekens. Dit is namelijk een punt, streepje, onderstrepingsteken, plusteken. De gebruikersnaam wordt gevolgd door het @-teken.

Laten we, gewapend met deze kennis, beginnen met het samenstellen van de reguliere expressie vanaf de linkerkant, die dient om de gebruikersnaam te controleren. Dit is wat we hebben:

^(+)@
Deze reguliere expressie kan als volgt worden gelezen: "Aan het begin van de regel moet ten minste één teken staan ​​van die in de groep tussen vierkante haken, en daarna moet er een @-teken staan."

Nu is het de hostnaam wachtrij - hostnaam . Dezelfde regels zijn hier van toepassing als voor de gebruikersnaam, dus de sjabloon ervoor ziet er als volgt uit:

(+)
Voor de top-level domeinnaam gelden speciale regels. Er mogen alleen alfabetische tekens zijn, die minimaal twee moeten zijn (zo bevatten dergelijke domeinen meestal een landcode) en niet meer dan vijf. Dit alles betekent dat de sjabloon voor het controleren van het laatste deel van het adres als volgt zal zijn:

\.({2,5})$
Je kunt het als volgt lezen: "Eerst moet er een punt zijn, dan - van 2 tot 5 alfabetische tekens, en daarna eindigt de regel."

Nadat we de patronen voor de afzonderlijke delen van de reguliere expressie hebben voorbereid, gaan we ze samenvoegen:

^(+)@(+)\.({2,5})$
Nu blijft het alleen om te testen wat er is gebeurd:

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


Een e-mailadres valideren met reguliere expressies

Het feit dat de aan awk doorgegeven tekst op het scherm wordt weergegeven, betekent dat het systeem het herkende als een e-mailadres.

Resultaten

Als de reguliere expressie voor het controleren van e-mailadressen die u aan het begin van het artikel ontmoette, toen volkomen onbegrijpelijk leek, hopen we dat het er nu niet langer uitziet als een betekenisloze reeks tekens. Als dit waar is, heeft dit materiaal zijn doel gediend. In feite zijn reguliere expressies een onderwerp waar je je hele leven mee kunt omgaan, maar zelfs het weinige dat we hebben geanalyseerd, kan je al helpen bij het schrijven van scripts die behoorlijk geavanceerde teksten verwerken.

In deze reeks materialen lieten we meestal heel eenvoudige voorbeelden zien van bash-scripts die letterlijk uit een paar regels bestonden. Laten we de volgende keer naar iets groters kijken.

Beste lezers! Gebruikt u reguliere expressies bij het verwerken van tekst in opdrachtregelscripts?

Om teksten in bash-scripts volledig te verwerken met sed en awk, hoef je alleen reguliere expressies te begrijpen. Implementaties van deze meest bruikbare tool zijn letterlijk overal te vinden, en hoewel alle reguliere expressies op een vergelijkbare manier zijn gerangschikt, gebaseerd op dezelfde ideeën, heeft het werken ermee bepaalde functies in verschillende omgevingen. Hier zullen we het hebben over reguliere expressies die geschikt zijn voor gebruik in Linux-opdrachtregelscripts.

Dit materiaal is bedoeld als een introductie tot reguliere expressies voor degenen die misschien niet weten wat reguliere expressies zijn. Laten we daarom bij het begin beginnen.

Wat zijn reguliere expressies?

Voor velen, wanneer ze voor het eerst reguliere expressies zien, komt meteen de gedachte op dat ze een nietszeggende wirwar van karakters voor zich hebben. Maar dit is natuurlijk verre van het geval. Kijk bijvoorbeeld eens naar deze regex

Naar onze mening zal zelfs een absolute beginner meteen begrijpen hoe het werkt en waarom je het nodig hebt :) Als je het niet helemaal begrijpt, lees dan gewoon verder en alles valt op zijn plaats.
Een reguliere expressie is een patroon dat programma's zoals sed of awk gebruiken om tekst te filteren. Sjablonen gebruiken gewone ASCII-tekens die zichzelf voorstellen, en zogenaamde metatekens die bijvoorbeeld een speciale rol spelen, waardoor je naar bepaalde groepen tekens kunt verwijzen.

Typen reguliere expressies

Implementaties van reguliere expressies in verschillende omgevingen, bijvoorbeeld in programmeertalen als Java, Perl en Python, in Linux-tools als sed, awk en grep, hebben bepaalde eigenaardigheden. Deze functies zijn afhankelijk van de zogenaamde reguliere expressieverwerkingsengines, die zich bezighouden met de interpretatie van patronen.
Linux heeft twee reguliere expressie-engines:

  • Een engine die de POSIX Basic Regular Expression (BRE)-standaard ondersteunt.
  • Een engine die de POSIX Extended Regular Expression (ERE)-standaard ondersteunt.

De meeste Linux-hulpprogramma's voldoen aan ten minste de POSIX BRE-standaard, maar sommige hulpprogramma's (inclusief sed) begrijpen slechts een subset van de BRE-standaard. Een van de redenen voor deze beperking is de wens om dergelijke hulpprogramma's zo snel mogelijk te maken in tekstverwerking.

De POSIX ERE-standaard wordt vaak geïmplementeerd in programmeertalen. Het stelt je in staat om veel tools te gebruiken bij het ontwikkelen van reguliere expressies. Dit kunnen bijvoorbeeld speciale tekenreeksen zijn voor veelgebruikte patronen, zoals het zoeken naar afzonderlijke woorden of reeksen getallen in de tekst. Awk ondersteunt de ERE-standaard.

Er zijn veel manieren om reguliere expressies te ontwikkelen, afhankelijk van de mening van de programmeur en van de kenmerken van de engine waaronder ze zijn gemaakt. Het is niet eenvoudig om generieke reguliere expressies te schrijven die elke engine kan begrijpen. Daarom zullen we ons concentreren op de meest gebruikte reguliere expressies en kijken naar de specifieke kenmerken van hun implementatie voor sed en awk.

POSIX BRE reguliere expressies

Misschien is het eenvoudigste BRE-patroon een reguliere expressie voor het vinden van een exacte overeenkomst van een reeks tekens in tekst. Zo ziet het zoeken naar een string in sed en awk eruit:

$ echo "Dit is een test" | sed -n "/test/p" $ echo "Dit is een test" | awk "/test/(druk $0 af)"

Tekst zoeken op patroon in sed

Tekst zoeken op patroon in awk

U zult merken dat het zoeken naar een bepaald patroon wordt uitgevoerd zonder rekening te houden met de exacte locatie van de tekst in de tekenreeks. Daarnaast maakt het aantal voorvallen niet uit. Nadat de reguliere expressie de gegeven tekst ergens in de tekenreeks heeft gevonden, wordt de tekenreeks als geschikt beschouwd en doorgegeven voor verdere verwerking.

Houd er bij het werken met reguliere expressies rekening mee dat ze hoofdlettergevoelig zijn:

$ echo "Dit is een test" | awk "/Test/(print $0)" $ echo "Dit is een test" | awk "/test/(druk $0 af)"

Reguliere expressies zijn hoofdlettergevoelig

De eerste reguliere expressie vond geen overeenkomsten, aangezien het woord "test", dat met een hoofdletter begint, niet in de tekst voorkomt. De tweede, geconfigureerd om te zoeken naar een woord dat in hoofdletters is geschreven, vond een geschikte string in de stream.

In reguliere expressies kunt u niet alleen letters gebruiken, maar ook spaties en cijfers:

$ echo "Dit is weer een test 2" | awk "/test 2/(druk $0 af)"

Een stuk tekst zoeken dat spaties en cijfers bevat

Spaties worden door de engine voor reguliere expressies behandeld als gewone tekens.

Speciale symbolen

Bij het gebruik van verschillende tekens in reguliere expressies, zijn er een paar dingen om in gedachten te houden. Er zijn bijvoorbeeld enkele speciale tekens of metatekens die een speciale benadering vereisen wanneer ze in een sjabloon worden gebruikt. Daar zijn ze:

.*^${}+?|()

Als een van deze nodig is in de sjabloon, moet deze worden geëscaped met een backslash (backslash) - .

Als u bijvoorbeeld een dollarteken in de tekst moet vinden, moet dit in de sjabloon worden opgenomen, voorafgegaan door een escape-teken. Laten we zeggen dat er een bestand mijnbestand is met de volgende tekst:

Er staat 10$ op mijn zak

Het dollarteken kan worden gedetecteerd met een patroon als dit:

$ awk "/$/(print $0)" mijnbestand

Een speciaal teken in een sjabloon gebruiken

Bovendien is de backslash ook een speciaal teken, dus als je hem in een sjabloon wilt gebruiken, moet je er ook aan ontsnappen. Het ziet eruit als twee schuine strepen die elkaar opvolgen:

$ echo "is een speciaal teken" | awk "/\/(druk $0 af)"

Backslash ontsnapt

Hoewel de slash niet in de bovenstaande lijst met speciale tekens staat, zal een poging om deze te gebruiken in een reguliere expressie die is geschreven voor sed of awk, resulteren in een fout:

Onjuist gebruik van een schuine streep in een sjabloon

Als het nodig is, moet het ook worden ontsnapt:

$ echo "3 / 2" | awk "///(druk $0 af)"

Ontsnappen aan een schuine streep

Ankersymbolen

Er zijn twee speciale tekens om een ​​patroon aan het begin of einde van een tekstreeks te verankeren. Met het hoofdlettersymbool - ^ kunt u reeksen tekens beschrijven die aan het begin van tekstregels staan. Als het patroon dat u zoekt ergens anders in de tekenreeks voorkomt, zal de reguliere expressie er niet op reageren. Het gebruik van dit symbool ziet er als volgt uit:

$ echo "welkom op de likegeeks-website" | awk "/^likegeeks/(print $0)" $ echo "likegeeks website" | awk "/^likegeeks/(print $0)"

Zoek een patroon aan het begin van een string

Het ^-symbool is ontworpen om te zoeken naar een patroon aan het begin van een regel, terwijl er ook rekening wordt gehouden met hoofdletters. Laten we eens kijken hoe dit de verwerking van een tekstbestand zal beïnvloeden:

$ awk "/^this/(print $0)" mijnbestand


Zoek naar een patroon aan het begin van een regel in tekst uit een bestand

Als u bij het gebruik van sed een escape ergens in een patroon plaatst, wordt deze behandeld als elk ander normaal teken:

$ echo "Deze ^ is een test" | sed -n "/s ^/p"

Kap niet aan begin patroon in sed

In awk, wanneer hetzelfde patroon wordt gebruikt, moet het gegeven teken worden geëscaped:

$ echo "Deze ^ is een test" | awk "/s ^/(druk $0 af)"

Een deksel niet aan het begin van een patroon in awk

Met het zoeken naar tekstfragmenten aan het begin van de regel kwamen we erachter. Wat als u iets aan het einde van een regel moet vinden?

Het dollarteken - $ , het ankerteken voor het einde van de regel, helpt ons hierbij:

$ echo "Dit is een test" | awk "/test$/(druk $0 af)"

Tekst zoeken aan het einde van een regel

Beide ankertekens kunnen in hetzelfde patroon worden gebruikt. Laten we het bestand myfile verwerken, waarvan de inhoud wordt weergegeven in de onderstaande afbeelding, met behulp van de volgende reguliere expressie:

$ awk "/^dit is een test$/(print $0)" mijnbestand


Een patroon dat speciale tekens gebruikt voor het begin en einde van een string

Zoals u kunt zien, reageerde de sjabloon alleen op een tekenreeks die volledig overeenkwam met de gegeven reeks tekens en hun locatie.

Ga als volgt te werk om lege regels uit te filteren met ankertekens:

$ awk "!/^$/(print $0)" mijnbestand

In deze sjabloon heb ik het ontkenningssymbool, het uitroepteken -! . Met dit patroon wordt gezocht naar lijnen die niets bevatten tussen het begin en het einde van de regel, en dankzij het uitroepteken worden alleen lijnen afgedrukt die niet overeenkomen met dit patroon.

Punt symbool

De punt wordt gebruikt om naar elk afzonderlijk teken te zoeken, behalve het teken voor de nieuwe regel. Laten we het bestand mijnbestand doorgeven aan zo'n reguliere expressie, waarvan de inhoud hieronder wordt gegeven:

$ awk "/.st/(print $0)" mijnbestand


Punt gebruiken in reguliere expressies

Zoals te zien is in de uitvoer, komen alleen de eerste twee regels van het bestand overeen met het patroon, omdat ze de reeks tekens "st" bevatten, voorafgegaan door een ander teken, terwijl de derde regel geen geschikte reeks bevat, en de vierde regel doet, maar het staat helemaal aan het begin van de regel.

Karakter klassen

Een punt komt overeen met elk afzonderlijk teken, maar wat als u de reeks tekens die u zoekt flexibeler wilt beperken? In een dergelijke situatie kunt u tekenklassen gebruiken.

Dankzij deze aanpak kun je een zoekopdracht organiseren voor elk personage uit een bepaalde set. Om een ​​tekenklasse te beschrijven, worden vierkante haken - gebruikt:

$ awk "/th/(print $0)" mijnbestand


Beschrijving van een tekenklasse in een reguliere expressie

Hier zoeken we naar een reeks tekens "th" voorafgegaan door het teken "o" of het teken "i".

Klassen zijn handig bij het zoeken naar woorden die kunnen beginnen met een hoofdletter of een kleine letter:

$ echo "dit is een test" | awk "/his is een test/(print $0)" $ echo "Dit is een test" | awk "/his is een test/(print $0)"

Zoek naar woorden die kunnen beginnen met een kleine letter of een hoofdletter

Karakterklassen zijn niet beperkt tot letters. Hier kunnen ook andere karakters worden gebruikt. Het is onmogelijk om van tevoren te zeggen in welke situatie de lessen nodig zullen zijn - het hangt allemaal af van het probleem dat wordt opgelost.

Karakterklassen negeren

Symboolklassen kunnen ook worden gebruikt om het hierboven beschreven omgekeerde probleem op te lossen. In plaats van te zoeken naar symbolen die in de klas zijn opgenomen, kunt u namelijk een zoekopdracht organiseren voor alles wat niet in de klas is opgenomen. Om dit gedrag van een reguliere expressie te bereiken, moet u een ^-teken voor de lijst met klassetekens plaatsen. Het ziet er zo uit:

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


Zoeken naar tekens die niet in een klas zitten

In dit geval worden reeksen tekens "th" gevonden, waarvoor geen "o" of "i" staat.

Tekenreeksen

In tekenklassen kun je reeksen tekens beschrijven met streepjes:

$ awk "/st/(print $0)" mijnbestand


Een reeks tekens in een tekenklasse beschrijven

In dit voorbeeld komt de reguliere expressie overeen met de tekenreeks "st" voorafgegaan door een willekeurig teken dat zich in alfabetische volgorde tussen de tekens "e" en "p" bevindt.

Bereiken kunnen ook worden gemaakt op basis van getallen:

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

Reguliere expressie voor het vinden van drie willekeurige getallen

Een tekenklasse kan meerdere bereiken bevatten:

$ awk "/st/(print $0)" mijnbestand


Karakterklasse bestaande uit meerdere bereiken

Deze reguliere expressie komt overeen met alle reeksen van "st" voorafgegaan door tekens uit de bereiken a-f en m-z .

Speciale karakterklassen

BRE heeft speciale tekenklassen die kunnen worden gebruikt bij het schrijven van reguliere expressies:

  • [[:alpha:]] - komt overeen met elk alfabetisch teken dat in hoofdletters of kleine letters is geschreven.
  • [[:alnum:]] - komt overeen met elk alfanumeriek teken, namelijk tekens in het bereik 0-9 , A-Z , a-z .
  • [[:blank:]] - Komt overeen met een spatie en een tab.
  • [[:digit:]] - elk numeriek teken van 0 tot 9 .
  • [[:upper:]] - alfabetische hoofdletters - A-Z .
  • [[:lower:]] - alfabetische tekens in kleine letters - a-z .
  • [[:print:]] - komt overeen met elk afdrukbaar teken.
  • [[:punct:]] - komt overeen met leestekens.
  • [[:spatie:]] - spatietekens, in het bijzonder - spatie, tab, tekens NL , FF , VT , CR .

U kunt speciale klassen gebruiken in sjablonen zoals deze:

$ echo "abc" | awk "/[[:alpha:]]/(print $0)" $ echo "abc" | awk "/[[:digit:]]/(print $0)" $ echo "abc123" | awk "/[[:cijfer:]]/(druk $0 af)"


Speciale tekenklassen in reguliere expressies

Asterisk symbool

Als u een asterisk achter een teken in een patroon plaatst, betekent dit dat de reguliere expressie werkt als het teken een willekeurig aantal keren in de tekenreeks voorkomt - inclusief de situatie waarin het teken afwezig is in de tekenreeks.

$ echo "test" | awk "/tes*t/(print $0)" $ echo "tessst" | awk "/tes*t/(druk $0 af)"


Het *-teken gebruiken in reguliere expressies

Dit jokerteken wordt meestal gebruikt om te werken met woorden die altijd verkeerd gespeld zijn, of voor woorden die anders gespeld kunnen worden:

$ echo "Ik hou van groene kleur" | awk "/colou*r/(print $0)" $ echo "Ik hou van groene kleur" | awk "/colou*r/(print $0)"

Een woord zoeken met verschillende spellingen

In dit voorbeeld komt dezelfde reguliere expressie overeen met zowel het woord "kleur" als het woord "kleur". Dit komt doordat het teken "u", gevolgd door een asterisk, afwezig kan zijn of meerdere keren achter elkaar kan voorkomen.

Een andere handige functie die voortkomt uit het sterretje, is om het te combineren met een punt. Door deze combinatie kan de reguliere expressie reageren op een willekeurig aantal tekens:

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


Sjabloon die reageert op een willekeurig aantal tekens

In dit geval maakt het niet uit hoeveel en welke tekens tussen de woorden "this" en "test" staan.

De asterisk kan ook worden gebruikt met tekenklassen:

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


Het sterretje gebruiken met tekenklassen

In alle drie de voorbeelden werkt de reguliere expressie omdat de asterisk na de tekenklasse betekent dat als een willekeurig aantal "a"- of "e"-tekens wordt gevonden, of als ze niet worden gevonden, de tekenreeks overeenkomt met het gegeven patroon.

POSIX ERE reguliere expressies

De POSIX ERE-sjablonen die door sommige Linux-hulpprogramma's worden ondersteund, kunnen extra tekens bevatten. Zoals eerder vermeld ondersteunt awk deze standaard, maar sed niet.

Hier zullen we kijken naar de meest gebruikte karakters in ERE-patronen, die handig voor u zullen zijn bij het maken van uw eigen reguliere expressies.

▍Vraagteken

Het vraagteken geeft aan dat het voorgaande teken één keer of helemaal niet in de tekst kan voorkomen. Dit karakter is een van de herhalingsmetakarakters. Hier zijn enkele voorbeelden:

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


Vraagteken in reguliere expressies

Zoals u kunt zien, komt de letter "s" in het derde geval twee keer voor, dus de reguliere expressie reageert niet op het woord "testst".

Het vraagteken kan ook worden gebruikt met tekenklassen:

$ 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 "teest" | awk "/t?st/(druk $0 af)"


Vraagteken- en tekenklassen

Als er geen karakters uit de klasse in de string voorkomen, of één ervan komt één keer voor, dan werkt de reguliere expressie, maar zodra er twee karakters in het woord verschijnen, vindt het systeem geen match meer voor het patroon in de tekst.

▍Plus-symbool

Het plusteken in het patroon geeft aan dat de reguliere expressie overeenkomt met de overeenkomst als het voorgaande teken een of meer keren in de tekst voorkomt. Tegelijkertijd zal een dergelijke constructie niet reageren op de afwezigheid van een symbool:

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


Plusteken in reguliere expressies

Als er in dit voorbeeld geen "e"-teken in het woord staat, zal de engine voor reguliere expressies geen overeenkomsten in de tekst vinden. Het plus-symbool werkt ook met tekenklassen - op deze manier is het vergelijkbaar met het sterretje en het vraagteken:

$ 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/(druk $0 af)"


Plusteken- en karakterklassen

In dit geval, als de tekenreeks een teken uit de klasse bevat, wordt aangenomen dat de tekst overeenkomt met het patroon.

▍ Krullende beugels

De accolades die in ERE-patronen kunnen worden gebruikt, zijn vergelijkbaar met de hierboven besproken tekens, maar ze stellen u in staat om nauwkeuriger het vereiste aantal voorkomens van het teken dat eraan voorafgaat te specificeren. U kunt een limiet in twee formaten opgeven:

  • n - een getal dat het exacte aantal gezochte voorvallen aangeeft
  • n, m - twee getallen die als volgt worden geïnterpreteerd: "ten minste n keer, maar niet meer dan m".

Hier zijn voorbeelden van de eerste optie:

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

Krullende accolades in patronen, het exacte aantal keren vinden

In oudere versies van awk moest je de --re-interval command-line switch gebruiken om het programma intervallen in reguliere expressies te laten herkennen, maar in nieuwere versies niet.

$ 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)"


Afstand tussen accolades

In dit voorbeeld moet het teken "e" 1 of 2 keer voorkomen in de string, dan zal de reguliere expressie reageren op de tekst.

Krullende accolades kunnen ook worden gebruikt met tekenklassen. De voor u al bekende principes zijn hier van toepassing:

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


Krullende accolades en karakterklassen

De sjabloon reageert op de tekst als het teken "a" of het teken "e" een of twee keer voorkomt.

▍Logisch "of" symbool

Symbool | - een verticale balk, betekent een logische "of" in reguliere expressies. Bij het verwerken van een reguliere expressie die meerdere fragmenten bevat, gescheiden door een dergelijk teken, zal de engine de geparseerde tekst als een overeenkomst beschouwen als deze overeenkomt met een van de fragmenten. Hier is een voorbeeld:

$ echo "Dit is een test" | awk "/test|exam/(print $0)" $ echo "Dit is een examen" | awk "/test|exam/(print $0)" $ echo "Dit is iets anders" | awk "/test|examen/(druk $0 af)"


Booleaanse "of" in reguliere expressies

In dit voorbeeld is de reguliere expressie geconfigureerd om te zoeken naar de woorden "test" of "exam" in de tekst. Let op het feit dat tussen de sjabloonfragmenten en het |-symbool dat ze scheidt. er mogen geen spaties zijn.

Reguliere expressiefragmenten kunnen worden gegroepeerd met haakjes. Als u een bepaalde reeks tekens groepeert, wordt deze door het systeem als een normaal teken waargenomen. Dat wil zeggen dat er bijvoorbeeld herhalingsmetatekens op kunnen worden toegepast. Hier is hoe het eruit ziet:

$ echo "Vind ik leuk" | awk "/Like(Geeks)?/(print $0)" $ echo "LikeGeeks" | awk "/Like(Geeks)?/(print $0)"


Fragmenten van reguliere expressies groeperen

In deze voorbeelden staat het woord "Geeks" tussen haakjes, gevolgd door een vraagteken. Bedenk dat het vraagteken "0 of 1 herhaling" betekent, met als resultaat dat de reguliere expressie overeenkomt met zowel de tekenreeks "Vind ik leuk" als de tekenreeks "LikeGeeks".

Praktijkvoorbeelden

Nu we de basis van reguliere expressies hebben behandeld, is het tijd om er iets nuttigs mee te doen.

▍Het aantal bestanden tellen

Laten we een bash-script schrijven dat bestanden telt die zich in mappen bevinden die naar de omgevingsvariabele PATH zijn geschreven. Om dit te doen, moet u eerst een lijst met paden naar mappen maken. Laten we dit doen met sed en dubbele punten vervangen door spaties:

$ echo $PATH | sed "s/:/ /g"

De opdracht Replace ondersteunt reguliere expressies als patronen voor het zoeken naar tekst. In dit geval is alles uiterst eenvoudig, we zijn op zoek naar een dubbele punt, maar niemand neemt de moeite om hier iets anders te gebruiken - het hangt allemaal af van de specifieke taak.
Nu moeten we de resulterende lijst in een lus doorlopen en de nodige acties uitvoeren om het aantal bestanden daar te tellen. Het algemene schema van het script is als volgt:

Mypath=$(echo $PATH | sed "s/:/ /g") voor directory in $mypath do done

Laten we nu de volledige tekst van het script schrijven, met behulp van de opdracht ls om informatie te krijgen over het aantal bestanden in elk van de mappen:

#!/bin/bash mypath=$(echo $PATH | sed "s/:/ /g") count=0 voor directory in $mypath do check=$(ls $directory) voor item in $check do count=$ [ $count + 1 ] done echo "$directory - $count" count=0 klaar

Bij het uitvoeren van het script kan blijken dat sommige mappen van PATH niet bestaan, maar dit belet niet dat bestanden in bestaande mappen worden geteld.


Aantal bestanden

De belangrijkste waarde van dit voorbeeld is dat je met dezelfde aanpak veel complexere problemen kunt oplossen. Welke hangt af van uw behoeften.

▍E-mailadressen verifiëren

Er zijn websites met enorme verzamelingen reguliere expressies waarmee u e-mailadressen, telefoonnummers, enzovoort kunt controleren. Het is echter één ding om kant-en-klaar te nemen, en iets heel anders om zelf iets te creëren. Laten we dus een reguliere expressie schrijven om e-mailadressen te valideren. Laten we beginnen met de analyse van de initiële gegevens. Hier is bijvoorbeeld een adres:

[e-mail beveiligd]

De gebruikersnaam, gebruikersnaam , kan bestaan ​​uit alfanumerieke tekens en enkele andere tekens. Dit is namelijk een punt, streepje, onderstrepingsteken, plusteken. De gebruikersnaam wordt gevolgd door het @-teken.

Laten we, gewapend met deze kennis, beginnen met het samenstellen van de reguliere expressie vanaf de linkerkant, die dient om de gebruikersnaam te controleren. Dit is wat we hebben:

^(+)@

Nu is het de hostnaam wachtrij - hostnaam . Dezelfde regels zijn hier van toepassing als voor de gebruikersnaam, dus de sjabloon ervoor ziet er als volgt uit:

(+)

Voor de top-level domeinnaam gelden speciale regels. Er mogen alleen alfabetische tekens zijn, die minimaal twee moeten zijn (zo bevatten dergelijke domeinen meestal een landcode) en niet meer dan vijf. Dit alles betekent dat de sjabloon voor het controleren van het laatste deel van het adres als volgt zal zijn:

.({2,5})$

Je kunt het als volgt lezen: "Eerst moet er een punt zijn, dan - van 2 tot 5 alfabetische tekens, en daarna eindigt de regel."

Nadat we de patronen voor de afzonderlijke delen van de reguliere expressie hebben voorbereid, gaan we ze samenvoegen:

^(+)@(+).({2,5})$

Nu blijft het alleen om te testen wat er is gebeurd:

$echo" [e-mail beveiligd]" | awk "/^(+)@(+).((2,5))$/(print $0)" $ echo " [e-mail beveiligd]" | awk "/^(+)@(+).((2,5))$/(print $0)"


Een e-mailadres valideren met reguliere expressies

Het feit dat de aan awk doorgegeven tekst op het scherm wordt weergegeven, betekent dat het systeem het herkende als een e-mailadres.

Resultaten

Als de reguliere expressie voor het controleren van e-mailadressen die u aan het begin van het artikel ontmoette, toen volkomen onbegrijpelijk leek, hopen we dat het er nu niet langer uitziet als een betekenisloze reeks tekens. Als dit waar is, heeft dit materiaal zijn doel gediend. In feite zijn reguliere expressies een onderwerp waar je je hele leven mee kunt omgaan, maar zelfs het weinige dat we hebben geanalyseerd, kan je al helpen bij het schrijven van scripts die behoorlijk geavanceerde teksten verwerken.

In deze reeks materialen lieten we meestal heel eenvoudige voorbeelden zien van bash-scripts die letterlijk uit een paar regels bestonden. Laten we de volgende keer naar iets groters kijken.

Beste lezers! Gebruikt u reguliere expressies bij het verwerken van tekst in opdrachtregelscripts?

Reguliere expressie Een tekstpatroon dat bestaat uit een combinatie van letters, cijfers en speciale tekens, ook wel metatekens genoemd. Een nauwe verwant van reguliere expressies zijn wildcard-expressies, die vaak worden gebruikt bij bestandsbeheer. Reguliere expressies worden voornamelijk gebruikt voor het matchen en zoeken van tekst. Veel gebruikt voor het ontleden van syntaxis.

UNIX-gebruikers zijn bekend met reguliere expressies van grep, sed, awk (of gawk) en ed. Met behulp van deze programma's of hun equivalenten kunt u de onderstaande voorbeelden proberen te verifiëren. Teksteditors zoals (X)Emacs en vi maken ook veel gebruik van reguliere expressies. Misschien is het bekendste en meest wijdverbreide gebruik van reguliere expressies in de Perl-taal. Het is moeilijk voor een softwareontwikkelaar en een systeembeheerder om zonder kennis van reguliere expressies te doen.

metakarakters

Strings kunnen dus bestaan ​​uit letters, cijfers en metatekens. De metatekens zijn:

\ | () { } ^ $ * + ? . < >

Metatekens kunnen de volgende rollen spelen in een reguliere expressie:

    kwantor

    stelling;

    groep teken;

    alternatief;

    reeks teken

Kwantificatoren

Het metateken * (sterretje) vervangt 0 of meer tekens. Het metateken + (plus) vervangt 1 of meer tekens. Metakarakter. (punt) vervangt precies 1 willekeurig teken. Metakarakter? (vraagteken) vervangt 0 of 1 teken. Het verschil in het gebruik van * en + is dat een zoekopdracht om te zoeken naar de tekenreeks c* alle tekenreeksen retourneert, inclusief lege, terwijl een zoekopdracht c+ alleen tekenreeksen teruggeeft die het teken c bevatten.

Lege regels zijn onderworpen aan de volgende conventies: een lege regel bevat één en slechts één lege regel; een niet-lege string bevat lege strings voor elk teken en ook aan het einde van de string.

Reguliere expressies gebruiken ook de constructie (n,m), wat betekent dat het teken dat aan de constructie voorafgaat n tot m keer voorkomt in een string. Als we het getal m weglaten, bedoelen we oneindig. Die. speciale gevallen van de constructie zijn de volgende vermeldingen: (0,) , (1,) en (0,1) . De eerste komt overeen met * , de tweede komt overeen met het metateken + en de derde komt overeen met ? . Deze gelijkheden worden gemakkelijk verkregen uit de definitie van de corresponderende kwantoren. Bovendien betekent de constructie (n) dat het teken precies n keer voorkomt.

In verband met het gebruik van enkele leestekens en wiskundige symbolen als meta-tekens, is een extra meta-teken \ (backslash, backslash) geïntroduceerd, die, wanneer het voor een meta-teken wordt geschreven, deze laatste in een regulier teken verandert. Die. ? is een kwantor, en \? - vraagteken.

Groepen

De hierboven beschreven kwantoren werken, zoals reeds vermeld, op het teken dat zich het dichtst bij hen aan de linkerkant bevindt (de laatste voorafgaande). Maar met deze beperking kunt u groepen omzeilen die metatekens (en) gebruiken in hun aanduiding. Deze karakters extraheren een subexpressie uit de expressie, die wordt gecombineerd tot een groep, waarop de kwantor wordt toegepast.

Voorbeeld:

staat voor (of vervangt)

Ho ho ho ho ho ho hoho

Het nesten van subexpressies is mogelijk, d.w.z. subexpressies van kleinere lengte kunnen worden geëxtraheerd uit een subexpressie.

alternatieven

Gevormd met behulp van het metateken | (verticale balk) die een logische "of" aangeeft.

Voorbeeld: reguliere expressie koeien(a|s|e|y|oy|oy)? zet alle mogelijke verbuigingen van het woord "koe" in het enkelvoud door gevallen.

Verklaringen

Er worden metatekens onderscheiden, die speciale objecten aanduiden - strings met een lengte van nul, die dienen om de plaats te bepalen van de tekst die eraan voorafgaat of erop volgt. Dergelijke objecten worden beweringen genoemd. De volgende instructies komen voor in reguliere expressies:

^ begin van regel $ einde van regel< начало слова >einde van woord

Voorbeeld: De reguliere expressie $The komt overeen met de tekenreeks die begint met The .

Opmerking: gewone tekens kunnen worden beschouwd als uitspraken met een lengte die niet nul is.

Opeenvolgingen

Een speciale constructie, ingesloten tussen metatekens [ en ] (rechthoekige haakjes), stelt u in staat om de varianten van tekens op te sommen die op een bepaalde plaats in een reguliere expressie kunnen voorkomen, en wordt een reeks genoemd. Binnen de vierkante haken worden alle metatekens behandeld als eenvoudige tekens, en de symbolen - (min) en ^ krijgen nieuwe betekenissen: met de eerste kunt u een doorlopende reeks tekens specificeren tussen de twee gespecificeerde, en de tweede geeft een logische "niet " (ontkenning). Het is het gemakkelijkst om de volgende voorbeelden te overwegen:

een van de kleine Latijnse letters:

latijns alfanumeriek teken (van a tot z , van A tot Z en van 0 tot 9):

niet-Latijns alfanumeriek teken:

[^a-zA-Z0-9]

elk woord (zonder koppeltekens, wiskundige symbolen en cijfers):

<+>

Voor de beknoptheid en eenvoud worden de volgende afkortingen geïntroduceerd:

\d is een cijfer (d.w.z. komt overeen met de uitdrukking ); \D is geen cijfer (d.w.z. [^0-9]); \w latijns woord (alfanumeriek); \W niet-witruimtetekenreeks die geen Latijns alfanumeriek woord is ([^a-zA-Z0-9]); \s lege ruimte [ \t\n\r\f] , d.w.z. spaties, tabbladen, enz. \S niet-leeg bereik ([^ \t\n\r\f]).

Associatie met jokertekens

Waarschijnlijk is elke gebruiker bekend met wildcards. Een voorbeeld van een wildcard-expressie is *.jpg , die verwijst naar alle bestanden met de extensie .jpg. Waarin verschillen reguliere expressies van jokertekens? De verschillen kunnen worden samengevat in drie regels voor het converteren van een willekeurige wildcard-expressie naar een reguliere expressie:

    Vervangen door.*

    Vervangen? op de.

    Vervang alle tekens die overeenkomen met metatekens door hun backslashed-varianten.

Inderdaad, in een reguliere expressie is de notatie * nutteloos en geeft een lege string, omdat betekent dat de lege string zo vaak als gewenst wordt herhaald. En hier.* (herhaal een willekeurig teken zo vaak als je wilt, inclusief 0) valt qua betekenis gewoon samen met het * teken in de set met jokertekens.

Een reguliere expressie die overeenkomt met *.jpg ziet er als volgt uit: .*\.jpg . En, bijvoorbeeld, de wildcard-reeksen ez*.pp komen overeen met twee equivalente reguliere expressies - ez.*\.pp en ez.*\.(cpp|hpp) .

Voorbeelden van reguliere expressies

E-mail in het formaat [e-mail beveiligd]

+(\.+)*@+(\.+)+

E-mail in het formaat "Ivan Ivanov "

("?+"?[ \t]*)+\<+(\.+)*@+(\.+)+\>

Het webprotocol in een URL controleren (http://, ftp:// of https://)

+://

Enkele C/C++-commando's en -richtlijnen:

^#include[ \t]+[<"][^>"]+[">] - inclusief richtlijn

//.+$ - commentaar op één regel

/\*[^*]*\*/ - commentaar op meerdere regels

-?+\.+ - getal met drijvende komma

0x+ - getal in hexadecimaal getalsysteem.

En hier is bijvoorbeeld een programma om naar het woord koe te zoeken:

grep -E "koe|vache" * >/ dev/ null && echo "Een koe gevonden"

Hier wordt de optie -E gebruikt om uitgebreide syntaxisondersteuning voor reguliere expressies in te schakelen.

Tekst gebaseerd op een artikel van Jan Borsodi uit het HOWTO-regexps.htm-bestand

Om teksten in bash-scripts volledig te verwerken met sed en awk, hoef je alleen reguliere expressies te begrijpen. Implementaties van deze meest bruikbare tool zijn letterlijk overal te vinden, en hoewel alle reguliere expressies op een vergelijkbare manier zijn gerangschikt, gebaseerd op dezelfde ideeën, heeft het werken ermee bepaalde functies in verschillende omgevingen. Hier zullen we het hebben over reguliere expressies die geschikt zijn voor gebruik in Linux-opdrachtregelscripts.

Dit materiaal is bedoeld als een introductie tot reguliere expressies voor degenen die misschien niet weten wat reguliere expressies zijn. Laten we daarom bij het begin beginnen.

Wat zijn reguliere expressies?

Voor velen, wanneer ze voor het eerst reguliere expressies zien, komt meteen de gedachte op dat ze een nietszeggende wirwar van karakters voor zich hebben. Maar dit is natuurlijk verre van het geval. Kijk bijvoorbeeld eens naar deze regex


Naar onze mening zal zelfs een absolute beginner meteen begrijpen hoe het werkt en waarom je het nodig hebt :) Als je het niet helemaal begrijpt, lees dan gewoon verder en alles valt op zijn plaats.
Een reguliere expressie is een patroon dat programma's zoals sed of awk gebruiken om tekst te filteren. Sjablonen gebruiken gewone ASCII-tekens die zichzelf voorstellen, en zogenaamde metatekens die bijvoorbeeld een speciale rol spelen, waardoor je naar bepaalde groepen tekens kunt verwijzen.

Typen reguliere expressies

Implementaties van reguliere expressies in verschillende omgevingen, bijvoorbeeld in programmeertalen als Java, Perl en Python, in Linux-tools als sed, awk en grep, hebben bepaalde eigenaardigheden. Deze functies zijn afhankelijk van de zogenaamde reguliere expressieverwerkingsengines, die zich bezighouden met de interpretatie van patronen.
Linux heeft twee reguliere expressie-engines:
  • Een engine die de POSIX Basic Regular Expression (BRE)-standaard ondersteunt.
  • Een engine die de POSIX Extended Regular Expression (ERE)-standaard ondersteunt.
De meeste Linux-hulpprogramma's voldoen aan ten minste de POSIX BRE-standaard, maar sommige hulpprogramma's (inclusief sed) begrijpen slechts een subset van de BRE-standaard. Een van de redenen voor deze beperking is de wens om dergelijke hulpprogramma's zo snel mogelijk te maken in tekstverwerking.

De POSIX ERE-standaard wordt vaak geïmplementeerd in programmeertalen. Het stelt je in staat om veel tools te gebruiken bij het ontwikkelen van reguliere expressies. Dit kunnen bijvoorbeeld speciale tekenreeksen zijn voor veelgebruikte patronen, zoals het zoeken naar afzonderlijke woorden of reeksen getallen in de tekst. Awk ondersteunt de ERE-standaard.

Er zijn veel manieren om reguliere expressies te ontwikkelen, afhankelijk van de mening van de programmeur en van de kenmerken van de engine waaronder ze zijn gemaakt. Het is niet eenvoudig om generieke reguliere expressies te schrijven die elke engine kan begrijpen. Daarom zullen we ons concentreren op de meest gebruikte reguliere expressies en kijken naar de specifieke kenmerken van hun implementatie voor sed en awk.

POSIX BRE reguliere expressies

Misschien is het eenvoudigste BRE-patroon een reguliere expressie voor het vinden van een exacte overeenkomst van een reeks tekens in tekst. Zo ziet het zoeken naar een string in sed en awk eruit:

$ echo "Dit is een test" | sed -n "/test/p" $ echo "Dit is een test" | awk "/test/(druk $0 af)"

Tekst zoeken op patroon in sed


Tekst zoeken op patroon in awk

U zult merken dat het zoeken naar een bepaald patroon wordt uitgevoerd zonder rekening te houden met de exacte locatie van de tekst in de tekenreeks. Daarnaast maakt het aantal voorvallen niet uit. Nadat de reguliere expressie de gegeven tekst ergens in de tekenreeks heeft gevonden, wordt de tekenreeks als geschikt beschouwd en doorgegeven voor verdere verwerking.

Houd er bij het werken met reguliere expressies rekening mee dat ze hoofdlettergevoelig zijn:

$ echo "Dit is een test" | awk "/Test/(print $0)" $ echo "Dit is een test" | awk "/test/(druk $0 af)"

Reguliere expressies zijn hoofdlettergevoelig

De eerste reguliere expressie vond geen overeenkomsten, aangezien het woord "test", dat met een hoofdletter begint, niet in de tekst voorkomt. De tweede, geconfigureerd om te zoeken naar een woord dat in hoofdletters is geschreven, vond een geschikte string in de stream.

In reguliere expressies kunt u niet alleen letters gebruiken, maar ook spaties en cijfers:

$ echo "Dit is weer een test 2" | awk "/test 2/(druk $0 af)"

Een stuk tekst zoeken dat spaties en cijfers bevat

Spaties worden door de engine voor reguliere expressies behandeld als gewone tekens.

Speciale symbolen

Bij het gebruik van verschillende tekens in reguliere expressies, zijn er een paar dingen om in gedachten te houden. Er zijn bijvoorbeeld enkele speciale tekens of metatekens die een speciale benadering vereisen wanneer ze in een sjabloon worden gebruikt. Daar zijn ze:

.*^${}\+?|()
Als een van deze nodig is in het patroon, moet deze worden geëscaped met een backslash (backslash) - \ .

Als u bijvoorbeeld een dollarteken in de tekst moet vinden, moet dit in de sjabloon worden opgenomen, voorafgegaan door een escape-teken. Laten we zeggen dat er een bestand mijnbestand is met de volgende tekst:

Er staat 10$ op mijn zak
Het dollarteken kan worden gedetecteerd met een patroon als dit:

$ awk "/\$/(print $0)" mijnbestand

Een speciaal teken in een sjabloon gebruiken

Bovendien is de backslash ook een speciaal teken, dus als je hem in een sjabloon wilt gebruiken, moet je er ook aan ontsnappen. Het ziet eruit als twee schuine strepen die elkaar opvolgen:

$ echo "\ is een speciaal teken" | awk "/\\/(druk $0 af)"

Backslash ontsnapt

Hoewel de slash niet in de bovenstaande lijst met speciale tekens staat, zal een poging om deze te gebruiken in een reguliere expressie die is geschreven voor sed of awk, resulteren in een fout:

$ echo "3 / 2" | awk "///(druk $0 af)"

Onjuist gebruik van een schuine streep in een sjabloon

Als het nodig is, moet het ook worden ontsnapt:

$ echo "3 / 2" | awk "/\//(druk $0 af)"

Ontsnappen aan een schuine streep

Ankersymbolen

Er zijn twee speciale tekens om een ​​patroon aan het begin of einde van een tekstreeks te verankeren. Met het hoofdlettersymbool - ^ kunt u reeksen tekens beschrijven die aan het begin van tekstregels staan. Als het patroon dat u zoekt ergens anders in de tekenreeks voorkomt, zal de reguliere expressie er niet op reageren. Het gebruik van dit symbool ziet er als volgt uit:

$ echo "welkom op de likegeeks-website" | awk "/^likegeeks/(print $0)" $ echo "likegeeks website" | awk "/^likegeeks/(print $0)"

Zoek een patroon aan het begin van een string

Het ^-symbool is ontworpen om te zoeken naar een patroon aan het begin van een regel, terwijl er ook rekening wordt gehouden met hoofdletters. Laten we eens kijken hoe dit de verwerking van een tekstbestand zal beïnvloeden:

$ awk "/^this/(print $0)" mijnbestand


Zoek naar een patroon aan het begin van een regel in tekst uit een bestand

Als u bij het gebruik van sed een escape ergens in een patroon plaatst, wordt deze behandeld als elk ander normaal teken:

$ echo "Deze ^ is een test" | sed -n "/s ^/p"

Kap niet aan begin patroon in sed

In awk, wanneer hetzelfde patroon wordt gebruikt, moet het gegeven teken worden geëscaped:

$ echo "Deze ^ is een test" | awk "/s \^/(druk $0 af)"

Een deksel niet aan het begin van een patroon in awk

Met het zoeken naar tekstfragmenten aan het begin van de regel kwamen we erachter. Wat als u iets aan het einde van een regel moet vinden?

Het dollarteken - $ , het ankerteken voor het einde van de regel, helpt ons hierbij:

$ echo "Dit is een test" | awk "/test$/(druk $0 af)"

Tekst zoeken aan het einde van een regel

Beide ankertekens kunnen in hetzelfde patroon worden gebruikt. Laten we het bestand myfile verwerken, waarvan de inhoud wordt weergegeven in de onderstaande afbeelding, met behulp van de volgende reguliere expressie:

$ awk "/^dit is een test$/(print $0)" mijnbestand


Een patroon dat speciale tekens gebruikt voor het begin en einde van een string

Zoals u kunt zien, reageerde de sjabloon alleen op een tekenreeks die volledig overeenkwam met de gegeven reeks tekens en hun locatie.

Ga als volgt te werk om lege regels uit te filteren met ankertekens:

$ awk "!/^$/(print $0)" mijnbestand
In deze sjabloon heb ik het ontkenningssymbool, het uitroepteken -! . Met dit patroon wordt gezocht naar lijnen die niets bevatten tussen het begin en het einde van de regel, en dankzij het uitroepteken worden alleen lijnen afgedrukt die niet overeenkomen met dit patroon.

Punt symbool

De punt wordt gebruikt om naar elk afzonderlijk teken te zoeken, behalve het teken voor de nieuwe regel. Laten we het bestand mijnbestand doorgeven aan zo'n reguliere expressie, waarvan de inhoud hieronder wordt gegeven:

$ awk "/.st/(print $0)" mijnbestand


Punt gebruiken in reguliere expressies

Zoals te zien is in de uitvoer, komen alleen de eerste twee regels van het bestand overeen met het patroon, omdat ze de reeks tekens "st" bevatten, voorafgegaan door een ander teken, terwijl de derde regel geen geschikte reeks bevat, en de vierde regel doet, maar het staat helemaal aan het begin van de regel.

Karakter klassen

Een punt komt overeen met elk afzonderlijk teken, maar wat als u de reeks tekens die u zoekt flexibeler wilt beperken? In een dergelijke situatie kunt u tekenklassen gebruiken.

Dankzij deze aanpak kun je een zoekopdracht organiseren voor elk personage uit een bepaalde set. Om een ​​tekenklasse te beschrijven, worden vierkante haken - gebruikt:

$ awk "/th/(print $0)" mijnbestand


Beschrijving van een tekenklasse in een reguliere expressie

Hier zoeken we naar een reeks tekens "th" voorafgegaan door het teken "o" of het teken "i".

Klassen zijn handig bij het zoeken naar woorden die kunnen beginnen met een hoofdletter of een kleine letter:

$ echo "dit is een test" | awk "/his is een test/(print $0)" $ echo "Dit is een test" | awk "/his is een test/(print $0)"

Zoek naar woorden die kunnen beginnen met een kleine letter of een hoofdletter

Karakterklassen zijn niet beperkt tot letters. Hier kunnen ook andere karakters worden gebruikt. Het is onmogelijk om van tevoren te zeggen in welke situatie de lessen nodig zullen zijn - het hangt allemaal af van het probleem dat wordt opgelost.

Karakterklassen negeren

Symboolklassen kunnen ook worden gebruikt om het hierboven beschreven omgekeerde probleem op te lossen. In plaats van te zoeken naar symbolen die in de klas zijn opgenomen, kunt u namelijk een zoekopdracht organiseren voor alles wat niet in de klas is opgenomen. Om dit gedrag van een reguliere expressie te bereiken, moet u een ^-teken voor de lijst met klassetekens plaatsen. Het ziet er zo uit:

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


Zoeken naar tekens die niet in een klas zitten

In dit geval worden reeksen tekens "th" gevonden, waarvoor geen "o" of "i" staat.

Tekenreeksen

In tekenklassen kun je reeksen tekens beschrijven met streepjes:

$ awk "/st/(print $0)" mijnbestand


Een reeks tekens in een tekenklasse beschrijven

In dit voorbeeld komt de reguliere expressie overeen met de tekenreeks "st" voorafgegaan door een willekeurig teken dat zich in alfabetische volgorde tussen de tekens "e" en "p" bevindt.

Bereiken kunnen ook worden gemaakt op basis van getallen:

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

Reguliere expressie voor het vinden van drie willekeurige getallen

Een tekenklasse kan meerdere bereiken bevatten:

$ awk "/st/(print $0)" mijnbestand


Karakterklasse bestaande uit meerdere bereiken

Deze reguliere expressie komt overeen met alle reeksen van "st" voorafgegaan door tekens uit de bereiken a-f en m-z .

Speciale karakterklassen

BRE heeft speciale tekenklassen die kunnen worden gebruikt bij het schrijven van reguliere expressies:
  • [[:alpha:]] - komt overeen met elk alfabetisch teken dat in hoofdletters of kleine letters is geschreven.
  • [[:alnum:]] - komt overeen met elk alfanumeriek teken, namelijk tekens in het bereik 0-9 , A-Z , a-z .
  • [[:blank:]] - Komt overeen met een spatie en een tab.
  • [[:digit:]] - elk numeriek teken van 0 tot 9 .
  • [[:upper:]] - alfabetische hoofdletters - A-Z .
  • [[:lower:]] - alfabetische tekens in kleine letters - a-z .
  • [[:print:]] - komt overeen met elk afdrukbaar teken.
  • [[:punct:]] - komt overeen met leestekens.
  • [[:spatie:]] - spatietekens, in het bijzonder - spatie, tab, tekens NL , FF , VT , CR .
U kunt speciale klassen gebruiken in sjablonen zoals deze:

$ echo "abc" | awk "/[[:alpha:]]/(print $0)" $ echo "abc" | awk "/[[:digit:]]/(print $0)" $ echo "abc123" | awk "/[[:cijfer:]]/(druk $0 af)"


Speciale tekenklassen in reguliere expressies

Asterisk symbool

Als u een asterisk achter een teken in een patroon plaatst, betekent dit dat de reguliere expressie werkt als het teken een willekeurig aantal keren in de tekenreeks voorkomt - inclusief de situatie waarin het teken afwezig is in de tekenreeks.

$ echo "test" | awk "/tes*t/(print $0)" $ echo "tessst" | awk "/tes*t/(druk $0 af)"


Het *-teken gebruiken in reguliere expressies

Dit jokerteken wordt meestal gebruikt om te werken met woorden die altijd verkeerd gespeld zijn, of voor woorden die anders gespeld kunnen worden:

$ echo "Ik hou van groene kleur" | awk "/colou*r/(print $0)" $ echo "Ik hou van groene kleur" | awk "/colou*r/(print $0)"

Een woord zoeken met verschillende spellingen

In dit voorbeeld komt dezelfde reguliere expressie overeen met zowel het woord "kleur" als het woord "kleur". Dit komt doordat het teken "u", gevolgd door een asterisk, afwezig kan zijn of meerdere keren achter elkaar kan voorkomen.

Een andere handige functie die voortkomt uit het sterretje, is om het te combineren met een punt. Door deze combinatie kan de reguliere expressie reageren op een willekeurig aantal tekens:

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


Sjabloon die reageert op een willekeurig aantal tekens

In dit geval maakt het niet uit hoeveel en welke tekens tussen de woorden "this" en "test" staan.

De asterisk kan ook worden gebruikt met tekenklassen:

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


Het sterretje gebruiken met tekenklassen

In alle drie de voorbeelden werkt de reguliere expressie omdat de asterisk na de tekenklasse betekent dat als een willekeurig aantal "a"- of "e"-tekens wordt gevonden, of als ze niet worden gevonden, de tekenreeks overeenkomt met het gegeven patroon.

POSIX ERE reguliere expressies

De POSIX ERE-sjablonen die door sommige Linux-hulpprogramma's worden ondersteund, kunnen extra tekens bevatten. Zoals eerder vermeld ondersteunt awk deze standaard, maar sed niet.

Hier zullen we kijken naar de meest gebruikte karakters in ERE-patronen, die handig voor u zullen zijn bij het maken van uw eigen reguliere expressies.

▍Vraagteken

Het vraagteken geeft aan dat het voorgaande teken één keer of helemaal niet in de tekst kan voorkomen. Dit karakter is een van de herhalingsmetakarakters. Hier zijn enkele voorbeelden:

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


Vraagteken in reguliere expressies

Zoals u kunt zien, komt de letter "s" in het derde geval twee keer voor, dus de reguliere expressie reageert niet op het woord "testst".

Het vraagteken kan ook worden gebruikt met tekenklassen:

$ 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 "teest" | awk "/t?st/(druk $0 af)"


Vraagteken- en tekenklassen

Als er geen karakters uit de klasse in de string voorkomen, of één ervan komt één keer voor, dan werkt de reguliere expressie, maar zodra er twee karakters in het woord verschijnen, vindt het systeem geen match meer voor het patroon in de tekst.

▍Plus-symbool

Het plusteken in het patroon geeft aan dat de reguliere expressie overeenkomt met de overeenkomst als het voorgaande teken een of meer keren in de tekst voorkomt. Tegelijkertijd zal een dergelijke constructie niet reageren op de afwezigheid van een symbool:

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


Plusteken in reguliere expressies

Als er in dit voorbeeld geen "e"-teken in het woord staat, zal de engine voor reguliere expressies geen overeenkomsten in de tekst vinden. Het plus-symbool werkt ook met tekenklassen - op deze manier is het vergelijkbaar met het sterretje en het vraagteken:

$ 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/(druk $0 af)"


Plusteken- en karakterklassen

In dit geval, als de tekenreeks een teken uit de klasse bevat, wordt aangenomen dat de tekst overeenkomt met het patroon.

▍ Krullende beugels

De accolades die in ERE-patronen kunnen worden gebruikt, zijn vergelijkbaar met de hierboven besproken tekens, maar ze stellen u in staat om nauwkeuriger het vereiste aantal voorkomens van het teken dat eraan voorafgaat te specificeren. U kunt een limiet in twee formaten opgeven:
  • n - een getal dat het exacte aantal gezochte voorvallen aangeeft
  • n, m - twee getallen die als volgt worden geïnterpreteerd: "ten minste n keer, maar niet meer dan m".
Hier zijn voorbeelden van de eerste optie:

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

Krullende accolades in patronen, het exacte aantal keren vinden

In oudere versies van awk moest je de --re-interval command-line switch gebruiken om het programma intervallen in reguliere expressies te laten herkennen, maar in nieuwere versies niet.

$ 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)"


Afstand tussen accolades

In dit voorbeeld moet het teken "e" 1 of 2 keer voorkomen in de string, dan zal de reguliere expressie reageren op de tekst.

Krullende accolades kunnen ook worden gebruikt met tekenklassen. De voor u al bekende principes zijn hier van toepassing:

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


Krullende accolades en karakterklassen

De sjabloon reageert op de tekst als het teken "a" of het teken "e" een of twee keer voorkomt.

▍Logisch "of" symbool

Symbool | - een verticale balk, betekent een logische "of" in reguliere expressies. Bij het verwerken van een reguliere expressie die meerdere fragmenten bevat, gescheiden door een dergelijk teken, zal de engine de geparseerde tekst als een overeenkomst beschouwen als deze overeenkomt met een van de fragmenten. Hier is een voorbeeld:

$ echo "Dit is een test" | awk "/test|exam/(print $0)" $ echo "Dit is een examen" | awk "/test|exam/(print $0)" $ echo "Dit is iets anders" | awk "/test|examen/(druk $0 af)"


Booleaanse "of" in reguliere expressies

In dit voorbeeld is de reguliere expressie geconfigureerd om te zoeken naar de woorden "test" of "exam" in de tekst. Let op het feit dat tussen de sjabloonfragmenten en het |-symbool dat ze scheidt. er mogen geen spaties zijn.

Reguliere expressiefragmenten kunnen worden gegroepeerd met haakjes. Als u een bepaalde reeks tekens groepeert, wordt deze door het systeem als een normaal teken waargenomen. Dat wil zeggen dat er bijvoorbeeld herhalingsmetatekens op kunnen worden toegepast. Hier is hoe het eruit ziet:

$ echo "Vind ik leuk" | awk "/Like(Geeks)?/(print $0)" $ echo "LikeGeeks" | awk "/Like(Geeks)?/(print $0)"


Fragmenten van reguliere expressies groeperen

In deze voorbeelden staat het woord "Geeks" tussen haakjes, gevolgd door een vraagteken. Bedenk dat het vraagteken "0 of 1 herhaling" betekent, met als resultaat dat de reguliere expressie overeenkomt met zowel de tekenreeks "Vind ik leuk" als de tekenreeks "LikeGeeks".

Praktijkvoorbeelden

Nu we de basis van reguliere expressies hebben behandeld, is het tijd om er iets nuttigs mee te doen.

▍Het aantal bestanden tellen

Laten we een bash-script schrijven dat bestanden telt die zich in mappen bevinden die naar de omgevingsvariabele PATH zijn geschreven. Om dit te doen, moet u eerst een lijst met paden naar mappen maken. Laten we dit doen met sed en dubbele punten vervangen door spaties:

$ echo $PATH | sed "s/:/ /g"
De opdracht Replace ondersteunt reguliere expressies als patronen voor het zoeken naar tekst. In dit geval is alles uiterst eenvoudig, we zijn op zoek naar een dubbele punt, maar niemand neemt de moeite om hier iets anders te gebruiken - het hangt allemaal af van de specifieke taak.
Nu moeten we de resulterende lijst in een lus doorlopen en de nodige acties uitvoeren om het aantal bestanden daar te tellen. Het algemene schema van het script is als volgt:

Mypath=$(echo $PATH | sed "s/:/ /g") voor directory in $mypath do done
Laten we nu de volledige tekst van het script schrijven, met behulp van de opdracht ls om informatie te krijgen over het aantal bestanden in elk van de mappen:

#!/bin/bash mypath=$(echo $PATH | sed "s/:/ /g") count=0 voor directory in $mypath do check=$(ls $directory) voor item in $check do count=$ [ $count + 1 ] done echo "$directory - $count" count=0 klaar
Bij het uitvoeren van het script kan blijken dat sommige mappen van PATH niet bestaan, maar dit belet niet dat bestanden in bestaande mappen worden geteld.


Aantal bestanden

De belangrijkste waarde van dit voorbeeld is dat je met dezelfde aanpak veel complexere problemen kunt oplossen. Welke hangt af van uw behoeften.

▍E-mailadressen verifiëren

Er zijn websites met enorme verzamelingen reguliere expressies waarmee u e-mailadressen, telefoonnummers, enzovoort kunt controleren. Het is echter één ding om kant-en-klaar te nemen, en iets heel anders om zelf iets te creëren. Laten we dus een reguliere expressie schrijven om e-mailadressen te valideren. Laten we beginnen met de analyse van de initiële gegevens. Hier is bijvoorbeeld een adres:

[e-mail beveiligd]
De gebruikersnaam, gebruikersnaam , kan bestaan ​​uit alfanumerieke tekens en enkele andere tekens. Dit is namelijk een punt, streepje, onderstrepingsteken, plusteken. De gebruikersnaam wordt gevolgd door het @-teken.

Laten we, gewapend met deze kennis, beginnen met het samenstellen van de reguliere expressie vanaf de linkerkant, die dient om de gebruikersnaam te controleren. Dit is wat we hebben:

^(+)@
Deze reguliere expressie kan als volgt worden gelezen: "Aan het begin van de regel moet ten minste één teken staan ​​van die in de groep tussen vierkante haken, en daarna moet er een @-teken staan."

Nu is het de hostnaam wachtrij - hostnaam . Dezelfde regels zijn hier van toepassing als voor de gebruikersnaam, dus de sjabloon ervoor ziet er als volgt uit:

(+)
Voor de top-level domeinnaam gelden speciale regels. Er mogen alleen alfabetische tekens zijn, die minimaal twee moeten zijn (zo bevatten dergelijke domeinen meestal een landcode) en niet meer dan vijf. Dit alles betekent dat de sjabloon voor het controleren van het laatste deel van het adres als volgt zal zijn:

\.({2,5})$
Je kunt het als volgt lezen: "Eerst moet er een punt zijn, dan - van 2 tot 5 alfabetische tekens, en daarna eindigt de regel."

Nadat we de patronen voor de afzonderlijke delen van de reguliere expressie hebben voorbereid, gaan we ze samenvoegen:

^(+)@(+)\.({2,5})$
Nu blijft het alleen om te testen wat er is gebeurd:

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


Een e-mailadres valideren met reguliere expressies

Het feit dat de aan awk doorgegeven tekst op het scherm wordt weergegeven, betekent dat het systeem het herkende als een e-mailadres.

Resultaten

Als de reguliere expressie voor het controleren van e-mailadressen die u aan het begin van het artikel ontmoette, toen volkomen onbegrijpelijk leek, hopen we dat het er nu niet langer uitziet als een betekenisloze reeks tekens. Als dit waar is, heeft dit materiaal zijn doel gediend. In feite zijn reguliere expressies een onderwerp waar je je hele leven mee kunt omgaan, maar zelfs het weinige dat we hebben geanalyseerd, kan je al helpen bij het schrijven van scripts die behoorlijk geavanceerde teksten verwerken.

In deze reeks materialen lieten we meestal heel eenvoudige voorbeelden zien van bash-scripts die letterlijk uit een paar regels bestonden. Laten we de volgende keer naar iets groters kijken.

Beste lezers! Gebruikt u reguliere expressies bij het verwerken van tekst in opdrachtregelscripts?