Hoe te controleren of een string een substring bevat in Bash

How Check If String Contains Substring Bash



De vraag is hoe te controleren of een string een substring bevat in Bash. Het antwoord is: gebruik Pattern Matching. Dit roept een andere vraag op, namelijk: wat is Pattern Matching? Welnu, een zin in een zin heeft bepaalde kenmerken. Daarom verschilt het van andere zinnen in dezelfde zin of in andere zinnen. De kenmerken kunnen worden gecodeerd als een patroon. Op die manier kan een bepaalde zin in een string worden geïdentificeerd. In dit artikel wordt uitgelegd hoe u een bepaalde subtekenreeks in een grotere tekenreeks identificeert, de subtekenreeks vervangt die overeenkomt met een andere subtekenreeks en elke subtekenreeks in een grotere tekenreeks op index lokaliseert. Voordat u echter in de uitleg duikt, moet u zich de verschillende manieren herinneren waarop een string in Bash tot stand wordt gebracht.

Tekenreeks door te ontsnappen aan spaties

Een string kan worden geconstrueerd door elke spatie te vervangen door de ontsnappingsreeks voor de spatie, ‘ ’; als in:







mijnVar=Toerismein Egypte is een van het land 's toonaangevende economische industrieën.
gooide uit $mijnVar

De uitvoer is:



Toerisme in Egypte is een van de belangrijkste economische industrieën van het land.



Opmerking: de apostrof gebruikte ook de ruimte-ontsnappingsreeks.





String door enkele aanhalingstekens

Heeft de programmeur de tijd om aan alle spaties in een string te ontsnappen? Nee. Daarom is het beter om twee enkele aanhalingstekens te gebruiken om een ​​string af te bakenen; zoals:

mijnVar='Toerisme in Egypte is er een van het land' ''s toonaangevende economische industrieën.'

Een string met enkele aanhalingstekens staat de uitbreiding (vervanging door het effect ervan) van een escape-reeks niet toe. Gelukkig, als twee strings naast elkaar worden gecodeerd, worden ze als één string beschouwd. Een escape-reeks kan ertussen worden ingevoegd, zoals hierboven is gedaan. De ontsnappingsreeks zou worden uitgebreid. Dus de uitvoer wordt:



Toerisme in Egypte is een van de belangrijkste economische industrieën van het land.

String door dubbele aanhalingstekens

Met dubbele aanhalingstekens worden escape-reeksen niet ook uitgebreid, maar variabelen worden uitgebreid. De volgende code illustreert dit:

mijnVar=Toerismein Egypte is een van het land 's toonaangevende economische industrieën.
gooide uit $mijnVar

De uitvoer is:

Toerisme in Egypte is een van de belangrijkste economische industrieën van het land.

Opmerking: de apostrof gebruikte ook de ruimte-ontsnappingsreeks.

In dit artikel is het belangrijkste type tekenreeks dat wordt overwogen de tekenreeks tussen enkele aanhalingstekens.

Basisprincipes van reguliere expressies

Regex

Overweeg deze reeks:

Deze wereld is niet echt ons thuis.

Laat de wereld de substring van interesse zijn. Vervolgens wordt de grote reeks (hele reeks) de doelreeks genoemd of eenvoudigweg het doel. De 'wereld' tussen aanhalingstekens wordt de reguliere expressie of eenvoudigweg regex genoemd. De inhoud, de wereld, is in dit geval het patroon.

Eenvoudige Matching

Als in de volgende code het woord 'wereld' in het doel wordt gevonden, zouden we zeggen dat het woord is gevonden.

P='Deze wereld is niet echt ons thuis.'
reg='wereld'
indien [[ $ str= ~$reg ]];dan
gooide uitgevonden
anders
gooide uitniet gevonden
zijn

=~ , de toewijzingsoperator gevolgd door ~ , wordt de bindingsoperator genoemd. De voorwaarde controleert of het patroon overeenkomt in de doeltekenreeks. Als een subtekenreeks die overeenkomt met het patroon in het doel wordt gevonden, wordt de echo-instructie Gevonden weergegeven. Als het niet wordt gevonden, wordt het echo-statement echo niet gevonden. De uitvoer voor deze code is:

gevonden

Zoals het patroon, de wereld, wordt gevonden in het doelwit. Merk op dat de scheidingsruimte na [[ en voor ]] behouden is gebleven.

Patroon

In de bovenstaande code is 'wereld' tussen aanhalingstekens de regex, terwijl de wereld zelf het patroon is. Dit is een duidelijk patroon. De meeste patronen zijn echter niet zo eenvoudig. Een patroon is een karakterisering van een te vinden substring. En dus gebruikt het Bash-patroon bepaalde metatekens. Een metakarakter is een karakter over andere karakters. Bash Pattern gebruikt bijvoorbeeld de volgende metatekens:

^ $ . * +? () [] {} |

Een reguliere expressie kan ook tussen de voorwaarde dubbele haakjes worden getypt. Maar het hoeft niet tussen aanhalingstekens te staan. Dus in dit geval is het letterlijk een patroon.

Karakter klassen

Vierkante haakjes

De uitvoer van de volgende code is gevonden, wat betekent dat er een overeenkomst heeft plaatsgevonden:

P='De kat kwam de kamer binnen.'
indien [[ $ str= ~[cbr]Bij]];dan
gooide uitgevonden
zijn

Het patroon, [cbr]at is match cat, dat begint met 'c', en dat doorgaat en eindigt met at. [cbr]at betekent, match 'c' of 'b' of 'r' gevolgd door at.

De uitvoer van de volgende code is gevonden, wat betekent dat er een overeenkomst heeft plaatsgevonden:

P='De vleermuis kwam de kamer binnen.'
indien [[ $ str= ~[cbr]Bij]];dan
gooide uitgevonden
zijn

Het patroon, [cbr]at heeft overeenkomende vleermuis, dat begint met 'b', en dat doorgaat en eindigt met at. [cbr]at betekent, match 'c' of 'b' of 'r' gevolgd door at.

De uitvoer van de volgende code is gevonden, wat betekent dat er een overeenkomst heeft plaatsgevonden:

P='De rat kwam de kamer binnen.'
indien [[ $ str= ~[cbr]Bij]];dan
gooide uitgevonden
zijn

Het patroon, [cbr]at heeft een match met rat, dat begint met 'r', en dat doorgaat en eindigt met at.

In de bovenstaande codevoorbeelden weet de programmeur niet of kat, vleermuis of rat in de doelreeks voorkomt. Maar hij weet dat de substring begint met 'c' of 'b' of 'r', dan verder gaat en eindigt met at. Door vierkante haken in een patroon kunnen verschillende mogelijke tekens overeenkomen met één teken op een positie ten opzichte van andere in het doel. Vierkante haken bevatten dus een reeks tekens, waarvan er één overeenkomt met een subtekenreeks. Ten slotte is het de volledige substring die wordt gematcht.

Bereik van tekens

In de bovenstaande code is [cbr] een klasse. Zelfs als 'c' of 'b' of 'r' overeenkomt met een enkel teken, als het daarop volgende meteen niet overeenkomt, komt het patroon nergens overeen.

Welnu, er zijn bepaalde reeksen die een klasse vormen. Zo vormen 0 tot 9 cijfers de klasse, [0-9] inclusief 0 en 9. Kleine letters 'a' tot 'z' vormen de klasse [a-z] met 'a' en 'z' inbegrepen. Hoofdletters 'A' tot 'Z' vormen de klasse [A-Z] met 'A' en 'Z' inbegrepen. Van een klasse is het een van de tekens die overeenkomen met één teken in de tekenreeks.

De volgende code levert een overeenkomst op:

indien [[ 'ID8id'= ~[0-9] ]];dan
gooide uitgevonden
zijn

Deze keer is het doel een letterlijke tekenreeks in de voorwaarde. 8, een van de mogelijke getallen binnen het bereik [0-9], komt overeen met 8 in de tekenreeks 'ID8id'. De bovenstaande code is gelijk aan:

indien [[ 'ID8id'= ~[0123456789] ]];dan
gooide uitgevonden
zijn

Hier zijn alle mogelijke getallen in het patroon geschreven, dus er is geen koppelteken.

In de volgende code wordt een overeenkomst verkregen:

indien [[ 'ID8iD'= ~[a-z] ]];dan
gooide uitgevonden
zijn

De overeenkomst is tussen kleine letters 'i' van het bereik, [a-z], en kleine letters 'i' van de doelreeks, 'ID8iD'.

Onthoud: het bereik is een klasse. De klas kan deel uitmaken van een groter patroon. Dus in een patroon kan tekst voor en/of na de les staan. De volgende code illustreert dit:

indien [[ 'ID8id is de identificatie'=~ ID[0-9]ID kaart ]];dan
gooide uitgevonden
zijn

De uitvoer is: gevonden. 'ID8id' uit het patroon komt overeen met 'ID8id' in de doelreeks.

Negatie

Overeenstemming wordt niet verkregen uit de volgende code:

indien [[ '0123456789101112'= ~[^0-9] ]];dan
gooide uitgevonden
anders
gooide uitniet gevonden
zijn

De uitvoer is:

niet gevonden

Zonder ^ voor het bereik, tussen vierkante haken, zou nul van het bereik overeenkomen met de eerste nul van de doelreeks. Dus, ^ voor een bereik (of optionele tekens) negeert de klasse.

De volgende code produceert een overeenkomst omdat de voorwaarde luidt: match elk niet-cijferig teken overal in het doel:

indien [[ 'ABCDEFGHIJ'= ~[^0-9] ]];dan
gooide uitgevonden
anders
gooide uitniet gevonden
zijn

De output is dus: gevonden .

[^0-9] betekent een niet-cijfer, dus [^0-9] is de ontkenning van [0-9] .

[^a-z] betekent een niet-kleine letter, dus [^a-z] is de ontkenning van [a-z] .

[^A-Z] betekent een niet-hoofdletter, dus [^A-Z] is de ontkenning van [A-Z] .

Andere ontkenningen zijn beschikbaar.

De punt (.) in het patroon

De punt (.) in het patroon komt overeen met elk teken, inclusief zichzelf. Beschouw de volgende code:

indien [[ '6759WXY.A3'= ~ 7.9W.Y.A]];dan
gooide uitgevonden
zijn

De uitvoer van de code wordt gevonden omdat de andere tekens overeenkomen. Eén stip komt overeen met '5'; een andere stip komt overeen met 'X'; en de laatste punt komt overeen met een punt.

Bijpassende afwisseling

Beschouw deze zin voor een doelstring:

De kooi heeft verschillende soorten vogels.

Misschien wil iemand weten of dit doelwit een duif of pauw of adelaar heeft. De volgende code kan worden gebruikt:

P='In de kooi zitten verschillende soorten pauwen.'
indien [[ $ str=~ duif|Pauw|Adelaar]];dan
gooide uitgevonden
anders
gooide uitniet gevonden
zijn

De uitvoer is gevonden. De afwisseling metateken, | in dienst is geweest. Er kunnen twee, drie, vier en meer alternatieven zijn. Wat in deze code overeenkomt, is 'pauw'.

Groepering

In het volgende patroon zijn haakjes gebruikt om tekens te groeperen:

een podium (danser)

De groep hier is een toneeldanseres omringd door de metakarakters ( en ) . (danser) is een subgroep, terwijl een podium (danser) de hele groep is. Stel je de volgende situatie voor:

De (danser is geweldig)

Hier, de subgroep of substring is, danser is geweldig.

Substrings met gemeenschappelijke delen

Een stakeholder is een persoon met een belang in een bedrijf. Stel je een bedrijf voor met een website, stake.com. Stel je voor dat een van de volgende doelreeksen zich in de computer bevindt:

De website, stake.com is voor het bedrijf.;

Daar is de belanghebbende.;

De stakeholder werkt voor stake.com.;

Laat een van deze strings het doelwit zijn. De programmeur wil misschien weten of stake.com of stakeholder zich in een doelstring bevindt. Zijn patroon zou zijn:

stake.com|stakeholder

afwisseling gebruiken.

inzet is twee keer getypt in de twee woorden. Dit kan worden voorkomen door het patroon als volgt te typen:

inzet(.com|houder)

.com|holder is in dit geval de subgroep.

Let op: het gebruik van het afwisselingsteken in dit geval. stake.com of stakeholder wordt nog steeds gezocht. De uitvoer van de volgende code wordt gevonden:

P='De website, stake.com is voor het bedrijf.'
indien [[ $ str=~ inzet(.met|houder) ]];dan
gooide uitgevonden
zijn

De substring die hier overeenkomt, is stake.com.

De BASH_REMATCH vooraf gedefinieerde array

BASH_REMATCH is een vooraf gedefinieerde array. Neem aan dat een patroon groepen heeft. De hele groep die overeenkomt, gaat de cel in voor index 0 van deze array. De eerste overeenkomende subgroep gaat naar de cel voor index 1; de tweede subgroep komt overeen, gaat naar de cel voor index 2, enzovoort. De volgende code laat zien hoe u deze array kunt gebruiken:

P='De toneeldanseres is gekomen.'
indien [[ $ str=~ podium(danser) ]];dan
gooide uitgevonden
zijn

voorlin ${!BASH_REMATCH[@]};doen
printf '${BASH_REMATCH[i]}, '
gedaan
gooide uit

De uitvoer is:

gevonden
toneeldanseres, danseres,

De hele groep is toneeldanseres. Er is maar één subgroep en dat is danseres.

Let op: de ruimte in het patroon is weggelaten.

Onafhankelijkheidsmatching in hoofdletters/kleine letters

Matching, zoals hierboven uitgelegd, is hoofdlettergevoelig. Matchen kan onafhankelijk van de zaak. Dit wordt geïllustreerd in de volgende code:

shopt -snocasematch

P='Wij houden van goede muziek.'
indien [[ $ str=~ Goed]];dan
gooide uitgevonden
zijn

shopt -unocasematch

De uitvoer is: gevonden. Het patroon is, Goed. De overeenkomende substring is 'goed'. Merk op hoe de nocasematch-optie is ingeschakeld aan het begin van het codesegment en uitgeschakeld aan het einde van het codesegment.

Lengte van een string

De syntaxis om de lengte van een string te verkrijgen is:

${#PARAMETER}

Voorbeeld:

P='Wij houden van goede muziek.'
gooide uit $ {# str}

De uitvoer is: 19.

Snaarreductie

De syntaxis voor stringreductie zijn:

${PARAMETER:OFFSET}
${PARAMETER:OFFSET:LENGTH}

waarbij het tellen voor OFFSET begint bij nul.

Het volgende voorbeeld laat zien hoe u de eerste 11 tekens van een tekenreeks verwijdert:

P='Ik dans altijd op goede muziek.'
gooide uit $ {str: 10}

De uitvoer is:

op goede muziek.

Tellen voor LENGTH begint vanaf het volgende teken. De volgende code laat zien hoe een gedeelte binnen de tekenreeks kan worden toegestaan:

P='Ik dans altijd op goede muziek.'
gooide uit $ {str: 10: 6}

De uitvoer is:

ance t

De eerste 11 tekens zijn verwijderd; de volgende 6 tekens waren toegestaan ​​en de rest van de tekens werd automatisch verwijderd.

Zoeken en vervangen

Wanneer een subtekenreeks wordt gevonden, kan deze worden vervangen door een andere subtekenreeks. De syntaxis hiervoor zijn:

waar=${PARAMETER/PATROON/VERVANGING}
waar=${PARAMETER//PATROON/VERVANGING}
waar=${PARAMETER/PATROON}
waar=${PARAMETER//PATROON}

Voor de eerste syntaxis met een enkele schuine streep naar voren wordt alleen de eerste overeenkomst vervangen. Voorbeeld:

P='Er is een rat, een vleermuis en een kat in de kamer.'
Rechtsaf=${str/[cbr]at/grote koe}
gooide uit $ str
gooide uit $ ret

De uitvoer is:

Er is een rat, een vleermuis en een kat, in de kamer.
Er is een grote koe, een vleermuis en een kat, in de kamer.

Voor de tweede syntaxis met dubbele schuine strepen naar voren, worden alle exemplaren van de overeenkomst vervangen. Voorbeeld:

P='Er is een rat, een vleermuis en een kat in de kamer.'
Rechtsaf=${str//[cbr]at/grote koe}
gooide uit $ str
gooide uit $ ret

De uitvoer is:

Er is een rat, een vleermuis en een kat, in de kamer.
Er is een grote koe, een grote koe en een grote koe, in de kamer.

Voor de derde syntaxis met een enkele schuine streep naar voren is er geen vervanging voor de eerste en enige overeenkomst.

Ook wordt de eerste gevonden subtekenreeks verwijderd. Voorbeeld:

P='Er is een rat, een vleermuis en een kat in de kamer.'
Rechtsaf=${str/[cbr]at}
gooide uit $ str
gooide uit $ ret

Voor de vierde syntaxis met dubbele schuine strepen naar voren is er geen vervanging voor alle overeenkomsten. Ook worden alle gevonden substrings verwijderd. Voorbeeld:

P='Er is een rat, een vleermuis en een kat in de kamer.'
Rechtsaf=${str//[cbr]at}
gooide uit $ str
gooide uit $ ret

De uitvoer is:

Er is een rat, een vleermuis en een kat, in de kamer.
Er is een , een en een , in de kamer.

Conclusie

Om te controleren of een string een substring heeft in Bash, moet Pattern Matching gebruikt worden. Pattern Matching vindt niet alleen plaats in de voorwaarde dubbele haakjes, [[ . . . ]]. Het kan ook plaatsvinden in parameteruitbreiding, met zijn ${. . .}. Met parameteruitbreiding is het mogelijk om een ​​substring te verkrijgen door middel van indexen.

Wat in dit artikel is gepresenteerd, zijn de meest kritische punten in Pattern Matching. Er zijn meer! Wat de lezer vervolgens moet bestuderen, is echter bestandsnaamuitbreiding.