Bash
Patroonaanpassing en reguliere expressies
Zoeken…
Syntaxis
- $ shopt -u optie # Deactiveer de ingebouwde 'optie' van Bash
- $ shopt -s optie # Activeer de ingebouwde 'optie' van Bash
Opmerkingen
Karakterklassen
Geldige tekenklassen voor de []
glob worden gedefinieerd door de POSIX-standaard:
alnum alpha ascii blanco cntrl cijfer grafiek onderste print punct spatie bovenste woord xdigit
Binnen []
meer dan één tekenklasse of bereik worden gebruikt, bijv.
$ echo a[a-z[:blank:]0-9]*
komt overeen met elk bestand dat begint met een a
en wordt gevolgd door een kleine letter of een spatie of een cijfer.
Houd er echter rekening mee dat een []
glob alleen volledig kan worden genegeerd en niet alleen delen ervan. Het ontkenningsteken moet het eerste teken zijn na de opening [
, deze uitdrukking komt bijvoorbeeld overeen met alle bestanden die niet met een a
$ echo [^a]*
Het volgende komt overeen met alle bestanden die beginnen met een cijfer of een ^
$ echo [[:alpha:]^a]*
Het komt niet overeen met een bestand of map die begint met letter behalve een a
omdat de ^
wordt geïnterpreteerd als een letterlijke ^
.
Ontsnappende glob karakters
Het is mogelijk dat een bestand of map een glob-teken bevat als onderdeel van de naam. In dit geval kan een glob ontsnapt worden met een voorafgaande \
voor een letterlijke match. Een andere benadering is om dubbele ""
of enkele ''
aanhalingstekens te gebruiken om het bestand te adresseren. Bash verwerkt geen globs die zijn ingesloten in ""
of ''
.
Verschil met reguliere expressies
Het belangrijkste verschil tussen globs en reguliere expressies is dat voor een geldige reguliere expressies een kwalificatie en een kwantificering vereist zijn. Een kwalificatie geeft aan wat moet worden vergeleken en een kwantificeerder geeft aan hoe vaak de kwalificatie moet worden gekoppeld. De equivalente RegEx voor de *
glob is .*
Waar .
staat voor elk karakter en *
staat voor nul of meer overeenkomsten met het vorige karakter. De equivalente RegEx voor de ?
glob is .{1}
. Zoals eerder, de kwalificatie .
komt overeen met een willekeurig karakter en de {1}
geeft aan dat deze exact één keer overeenkomt met de voorgaande kwalificatie. Dit moet niet worden verward met de ?
kwantificator, die overeenkomt met nul of eenmaal in een RegEx. De []
glob is kan op dezelfde manier worden gebruikt in een RegEx, zolang deze wordt gevolgd door een verplichte kwantificator.
Gelijkwaardige reguliere expressies
glob | RegEx |
---|---|
* | .* |
? | . |
[] | [] |
Controleer of een string overeenkomt met een reguliere expressie
Controleer of een string uit precies 8 cijfers bestaat:
$ date=20150624
$ [[ $date =~ ^[0-9]{8}$ ]] && echo "yes" || echo "no"
yes
$ date=hello
$ [[ $date =~ ^[0-9]{8}$ ]] && echo "yes" || echo "no"
no
De * glob
Voorbereiding
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
De asterisk * is waarschijnlijk de meest gebruikte glob. Het komt eenvoudig overeen met elke string
$ echo *acy
macy stacy tracy
Een enkele * komt niet overeen met bestanden en mappen die zich in submappen bevinden
$ echo *
emptyfolder folder macy stacy tracy
$ echo folder/*
folder/anotherfolder folder/subfolder
De ** glob
Voorbereiding
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -s globstar
Bash kan twee aangrenzende sterretjes interpreteren als een enkele glob. Als de globstar
optie is geactiveerd, kan dit worden gebruikt om mappen te matchen die dieper in de mappenstructuur staan
echo **
emptyfolder folder folder/anotherfolder folder/anotherfolder/content folder/anotherfolder/content/deepfolder folder/anotherfolder/content/deepfolder/file folder/subfolder folder/subfolder/content folder/subfolder/content/deepfolder folder/subfolder/content/deepfolder/file macy stacy tracy
De **
kan worden gedacht aan een paduitbreiding, ongeacht hoe diep het pad is. Dit voorbeeld komt overeen met elk bestand of elke map die begint met deep
, ongeacht hoe diep het is genest:
$ echo **/deep*
folder/anotherfolder/content/deepfolder folder/subfolder/content/deepfolder
De ? glob
Voorbereiding
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
De ?
komt eenvoudig overeen met exact één karakter
$ echo ?acy
macy
$ echo ??acy
stacy tracy
De [] glob
Voorbereiding
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
Als het nodig is om specifieke tekens te matchen, kan '[]' worden gebruikt. Elk teken in '[]' wordt exact één keer gematcht.
$ echo [m]acy
macy
$ echo [st][tr]acy
stacy tracy
De []
glob is echter veelzijdiger dan alleen dat. Het zorgt ook voor een negatieve match en zelfs bijpassende reeksen karakters en karakterklassen. Een negatieve match wordt bereikt door het gebruik van !
of ^
als het eerste teken na [
. We kunnen stacy
matchen met
$ echo [!t][^r]acy
stacy
Hier vertellen we bash dat we alleen bestanden willen matchen die niet met een t
en de tweede letter is geen r
en het bestand eindigt op acy
.
Bereik kan worden gekoppeld door een paar tekens te scheiden met een koppelteken ( -
). Elk personage dat tussen deze twee insluitende personages valt - inclusief - wordt gekoppeld. Bijvoorbeeld, [rt]
is equivalent aan [rst]
$ echo [r-t][r-t]acy
stacy tracy
Karakterklassen kunnen worden gekoppeld aan [:class:]
, bijvoorbeeld om bestanden te matchen die een spatie bevatten
$ echo *[[:blank:]]*
file with space
Overeenkomende verborgen bestanden
Voorbereiding
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
Met de ingebouwde optie dotglob van Bash kunnen verborgen bestanden en mappen, dat wil zeggen bestanden en mappen die met een beginnen, overeenkomen .
$ shopt -s dotglob
$ echo *
file with space folder .hiddenfile macy stacy tracy
Niet hoofdlettergevoelig zoeken
Voorbereiding
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
Als u de optie nocaseglob
komt de glob overeen op een hoofdletterongevoelige manier
$ echo M*
M*
$ shopt -s nocaseglob
$ echo M*
macy
Gedrag wanneer een glob niets overeenkomt
Voorbereiding
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
In het geval dat de glob niets overeenkomt, wordt het resultaat bepaald door de opties nullglob
en failglob
. Als geen van beide is ingesteld, retourneert Bash de glob zelf als er niets is gevonden
$ echo no*match
no*match
Als nullglob
is geactiveerd, wordt niets ( null
) geretourneerd:
$ shopt -s nullglob
$ echo no*match
$
Als failglob
is geactiveerd, wordt een foutbericht geretourneerd:
$ shopt -s failglob
$ echo no*match
bash: no match: no*match
$
Let op, dat de failglob
optie vervangt de nullglob
optie, dat wil zeggen, als nullglob
en failglob
beide zijn ingesteld, dan - in geval van no match - wordt een fout geretourneerd.
Uitgebreide bolling
Voorbereiding
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
De ingebouwde extglob
optie van Bash kan de matchingmogelijkheden van een glob uitbreiden
shopt -s extglob
De volgende subpatronen omvatten geldige uitgebreide globs:
-
?(pattern-list)
- Komt overeen met nul of één voorkomen van de gegeven patronen -
*(pattern-list)
- Komt overeen met nul of meer voorkomens van de gegeven patronen -
+(pattern-list)
- Komt overeen met een of meer gevallen van de gegeven patronen -
@(pattern-list)
- Komt overeen met een van de gegeven patronen -
!(pattern-list)
- Komt overeen met alles behalve één van de gegeven patronen
De pattern-list
is een lijst met bollen gescheiden door |
.
$ echo *([r-t])acy
stacy tracy
$ echo *([r-t]|m)acy
macy stacy tracy
$ echo ?([a-z])acy
macy
De pattern-list
zelf kan een andere, geneste uitgebreide glob zijn. In het bovenstaande voorbeeld hebben we gezien dat we tracy
en stacy
kunnen matchen met *(rt)
. Deze uitgebreide glob zelf kan worden gebruikt in de ontkende uitgebreide glob !(pattern-list)
om overeen te komen met macy
$ echo !(*([r-t]))acy
macy
Het komt overeen met alles wat niet begint met nul of meer voorkomen van de letters r
, s
en t
, waardoor alleen macy
als mogelijke match macy
.
Regex-matching
pat='[^0-9]+([0-9]+)'
s='I am a string with some digits 1024'
[[ $s =~ $pat ]] # $pat must be unquoted
echo "${BASH_REMATCH[0]}"
echo "${BASH_REMATCH[1]}"
Output:
I am a string with some digits 1024
1024
In plaats van de regex toe te wijzen aan een variabele ( $pat
) zouden we ook kunnen doen:
[[ $s =~ [^0-9]+([0-9]+) ]]
Uitleg
- Het construct
[[ $s =~ $pat ]]
voert de regex-matching uit - De gevangen groepen, dwz de wedstrijdresultaten zijn beschikbaar in een array met de naam BASH_REMATCH
- De 0e index in de array BASH_REMATCH is de totale overeenkomst
- De i'de index in de BASH_REMATCH array is de i'th gevangen groep, waar i = 1, 2, 3 ...
Krijg gevangen groepen van een regex-match tegen een string
a='I am a simple string with digits 1234'
pat='(.*) ([0-9]+)'
[[ "$a" =~ $pat ]]
echo "${BASH_REMATCH[0]}"
echo "${BASH_REMATCH[1]}"
echo "${BASH_REMATCH[2]}"
Output:
I am a simple string with digits 1234
I am a simple string with digits
1234