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