Bash
Dopasowywanie wzorców i wyrażenia regularne
Szukaj…
Składnia
- $ shopt -u opcja # Dezaktywuj wbudowaną „opcję” Bash
- $ shopt -s opcja # Aktywuj wbudowaną „opcję” Bash
Uwagi
Klasy postaci
Prawidłowe klasy znaków dla globu [] są zdefiniowane przez standard POSIX:
alnum alpha ascii puste cntrl cyfra wykres dolny druk punktowa przestrzeń górne słowo xdigit
Wewnątrz [] można użyć więcej niż jednej klasy znaków lub zakresu, np.
$ echo a[a-z[:blank:]0-9]*
dopasuje każdy plik, który zaczyna się od a a po nim albo mała litera, albo spacja albo cyfra.
Należy jednak pamiętać, że glob [] można całkowicie negować, a nie tylko jego części. Znak negujący musi być pierwszym znakiem po otwarciu [ np. To wyrażenie pasuje do wszystkich plików, które nie zaczynają się od a
$ echo [^a]*
Poniższe dopasowanie pasuje do wszystkich plików, które zaczynają się cyfrą lub ^
$ echo [[:alpha:]^a]*
To nie pasuje do żadnej plik lub folder, którego nazwa zaczyna się na literę z wyjątkiem a ponieważ ^ jest interpretowany jako dosłowny ^ .
Uciekające globalne postacie
Możliwe jest, że plik lub folder zawiera znak glob jako część nazwy. W takim przypadku glob może być poprzedzony znakiem \ , aby uzyskać dosłowne dopasowanie. Innym sposobem jest użycie podwójnego "" lub pojedyncze '' cytuje zająć plik. Bash nie przetwarza globów, które są ujęte w "" lub '' .
Różnica w stosunku do wyrażeń regularnych
Najważniejsza różnica między globami a wyrażeniami regularnymi polega na tym, że prawidłowe wyrażenia regularne wymagają zarówno kwalifikatora, jak i kwantyfikatora. Kwalifikator określa, co należy dopasować, a kwantyfikator określa, jak często dopasowywać kwalifikator. Odpowiednik RegEx do * glob to .* Gdzie . oznacza dowolny znak, a * oznacza zero lub więcej dopasowań poprzedniego znaku. Odpowiednik RegEx dla ? glob is .{1} . Tak jak poprzednio, kwalifikator . pasuje do dowolnego znaku, a {1} wskazuje, że dokładnie pasuje do poprzedniego kwalifikatora. Nie należy tego mylić z ? kwantyfikator, który dopasowuje zero lub jeden raz w RegEx. Glob [] może być używany tak samo w RegEx, pod warunkiem, że następuje po nim obowiązkowy kwantyfikator.
Równoważne wyrażenia regularne
| Glob | RegEx |
|---|---|
* | .* |
? | . |
[] | [] |
Sprawdź, czy ciąg znaków pasuje do wyrażenia regularnego
Sprawdź, czy ciąg składa się z dokładnie 8 cyfr:
$ date=20150624
$ [[ $date =~ ^[0-9]{8}$ ]] && echo "yes" || echo "no"
yes
$ date=hello
$ [[ $date =~ ^[0-9]{8}$ ]] && echo "yes" || echo "no"
no
* Glob
Przygotowanie
$ 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
Gwiazdka * jest prawdopodobnie najczęściej używanym globem. Po prostu pasuje do dowolnego ciągu
$ echo *acy
macy stacy tracy
Pojedynczy * nie będzie pasował do plików i folderów znajdujących się w podfolderach
$ echo *
emptyfolder folder macy stacy tracy
$ echo folder/*
folder/anotherfolder folder/subfolder
** glob
Przygotowanie
$ 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 jest w stanie zinterpretować dwie sąsiednie gwiazdki jako jedną glob. Po globstar opcji globstar można jej użyć do dopasowania folderów znajdujących się głębiej w strukturze katalogów
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
** można myśleć o rozszerzeniu ścieżki, bez względu na głębokość ścieżki. Ten przykład pasuje do dowolnego pliku lub folderu rozpoczynającego się od deep , niezależnie od tego, jak głęboko jest zagnieżdżony:
$ echo **/deep*
folder/anotherfolder/content/deepfolder folder/subfolder/content/deepfolder
The? glob
Przygotowanie
$ 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
The ? po prostu dopasowuje dokładnie jedną postać
$ echo ?acy
macy
$ echo ??acy
stacy tracy
The [] glob
Przygotowanie
$ 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
Jeśli istnieje potrzeba dopasowania określonych znaków, można użyć „[]”. Każda postać w „[]” zostanie dopasowana dokładnie raz.
$ echo [m]acy
macy
$ echo [st][tr]acy
stacy tracy
Glob [] jednak bardziej wszechstronny. Umożliwia także dopasowanie ujemne, a nawet dopasowanie zakresów znaków i klas znaków. Użycie ujemnego dopasowania jest możliwe ! lub ^ jako pierwszy znak po [ . Możemy dopasować stacy przez
$ echo [!t][^r]acy
stacy
Tutaj mówimy bashowi, że chcemy dopasować tylko pliki, które nie zaczynają się na t a druga litera nie jest r a plik kończy się na acy .
Zakresy można dopasować, oddzielając parę znaków łącznikiem ( - ). Każda postać, która znajdzie się pomiędzy tymi dwoma otaczającymi postaciami - włącznie - zostanie dopasowana. Np. [rt] jest równoważne z [rst]
$ echo [r-t][r-t]acy
stacy tracy
Klasy znaków można dopasować za pomocą [:class:] , np. W celu dopasowania plików zawierających spacje
$ echo *[[:blank:]]*
file with space
Dopasowywanie ukrytych plików
Przygotowanie
$ 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
Wbudowana opcja Bash dotglob pozwala dopasować ukryte pliki i foldery, tj. Pliki i foldery zaczynające się od .
$ shopt -s dotglob
$ echo *
file with space folder .hiddenfile macy stacy tracy
Dopasowywanie bez rozróżniania wielkości liter
Przygotowanie
$ 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
Ustawienie opcji nocaseglob dopasuje glob do wielkości liter bez rozróżniania wielkości liter
$ echo M*
M*
$ shopt -s nocaseglob
$ echo M*
macy
Zachowanie, gdy glob nie pasuje do niczego
Przygotowanie
$ 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
Jeśli glob nie pasuje do niczego, wynik jest określany przez opcje nullglob i failglob . Jeśli żadna z nich nie zostanie ustawiona, Bash zwróci glob, jeśli nic nie zostanie dopasowane
$ echo no*match
no*match
Jeśli nullglob jest aktywowany, nic ( null ) nie jest zwracane:
$ shopt -s nullglob
$ echo no*match
$
Jeśli aktywowana jest funkcja failglob jest komunikat o błędzie:
$ shopt -s failglob
$ echo no*match
bash: no match: no*match
$
Zauważ, że opcja failglob zastępuje opcję nullglob , tzn. Jeśli zarówno nullglob i failglob są ustawione, wówczas - w przypadku braku dopasowania - zwracany jest błąd.
Rozszerzone globowanie
Przygotowanie
$ 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
Wbudowana opcja Bash extglob może rozszerzyć możliwości dopasowania globu
shopt -s extglob
Następujące pod-wzorce obejmują prawidłowe rozszerzone globusy:
-
?(pattern-list)- Dopasowuje zero lub jedno wystąpienie podanych wzorów -
*(pattern-list)- Dopasowuje zero lub więcej wystąpień podanych wzorów -
+(pattern-list)- Dopasowuje jedno lub więcej wystąpień podanych wzorów -
@(pattern-list)- Dopasowuje jeden z podanych wzorów -
!(pattern-list)- Dopasowuje wszystko oprócz jednego z podanych wzorów
Lista pattern-list to lista globów oddzielonych | .
$ echo *([r-t])acy
stacy tracy
$ echo *([r-t]|m)acy
macy stacy tracy
$ echo ?([a-z])acy
macy
Sama pattern-list może być kolejnym zagnieżdżonym rozszerzonym globem. W powyższym przykładzie widzieliśmy, że możemy dopasować tracy i stacy do *(rt) . Ten rozszerzony glob sam w sobie może być używany w negowanym rozszerzonym glob !(pattern-list) w celu dopasowania macy
$ echo !(*([r-t]))acy
macy
Pasuje do wszystkiego, co nie zaczyna się od zera lub więcej wystąpień liter r , s i t , co pozostawia tylko macy jako możliwe dopasowanie.
Dopasowywanie wyrażeń regularnych
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]}"
Wynik:
I am a string with some digits 1024
1024
Zamiast przypisywać regex do zmiennej ( $pat ), moglibyśmy również:
[[ $s =~ [^0-9]+([0-9]+) ]]
Wyjaśnienie
- Konstrukcja
[[ $s =~ $pat ]]wykonuje dopasowanie wyrażenia regularnego - Przechwycone grupy, tj. Wyniki dopasowania są dostępne w tablicy o nazwie BASH_REMATCH
- Indeks 0 w tablicy BASH_REMATCH to całkowite dopasowanie
- Indeks i'th w tablicy BASH_REMATCH jest i'th ujęte grupa, gdzie i = 1, 2, 3 ...
Uzyskaj przechwycone grupy z wyrażenia regularnego względem łańcucha
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]}"
Wynik:
I am a simple string with digits 1234
I am a simple string with digits
1234