Jaka jest różnica między a[bc]d
i a{b,c}d
? Dlaczego ludzie używają, a{b,c}d
gdy już jest a[bc]d
?
ls
i kiedykolwiek spróbujesz tylko pojedynczych znaków, będą one wyglądać tak samo.
Jaka jest różnica między a[bc]d
i a{b,c}d
? Dlaczego ludzie używają, a{b,c}d
gdy już jest a[bc]d
?
ls
i kiedykolwiek spróbujesz tylko pojedynczych znaków, będą one wyglądać tak samo.
Odpowiedzi:
Te dwa są całkiem różne.
a[bc]d
to wzorzec nazwy pliku (w powłokach innych niż fish
). Rozwinie się do dwóch nazw plików abd
i acd
jeśli są to nazwy istniejących plików w bieżącym katalogu.
[...]
Część jest nawias wyrażenie, które dopasowuje pojedynczy znak z tych wymienionych (lub elementy zestawiania gdy zakresy są w zestawie). Pasujące do wzorca a[bc]d
, postać między strunami a
i d
w pliku musi być albo b
albo c
.
Jeśli abd
istnieje, ale acd
nie istnieje, rozszerzyłby się tylko abd
i odwrotnie.
Jeśli nie abd
, nie acd
istnieją, w zależności od powłoki i opcji, to spowodowałoby błąd (oryginalna Unix sh
, (t)csh
, zsh
, fish
, bash -O failglob
) i ewentualnie wyjść z powłoki lub opuszczają unexpanded¹ wzoru (Bourne'a jak i rc
-jak muszle) lub rozwinąć się nic ( bash/zsh/yash -o nullglob
niektóre starsze wersje fish
oryginalnego Uniksa sh
i (t)csh
jeśli w tym samym poleceniu są inne pasujące globusy).
a{b,c}d
jest rozszerzeniem nawiasów klamrowych (w powłokach, które je obsługują). Rozwinie się do dwóch ciągów abd
i acd
.
{...}
Część jest przecinkami ograniczony zestaw łańcuchów (w tym przykładzie, w niektórych powłoki, mogą być też szereg takich jak a..k
lub 20..25
lub więcej zaawansowanych, jak 00..20..2
i 0..20..2%02d
) i rozszerzenie jest obliczana przez łączenie każdego z tych łańcuchów z flankującymi ciągi a
i d
. Te ciągi znaków mogą być dłuższe niż pojedynczy znak i same mogą być rozszerzeniami nawiasów klamrowych.
Rozwijanie odbywa się niezależnie od tego, czy te ciągi odpowiadają istniejącym nazwom plików, czy nie.
Jeśli konstruujesz ciągi, użyj rozwinięcia nawiasu. Jeśli pasujesz nazwy plików, użyj wzorca nazwy pliku.
¹ W tym konkretnym przypadku a[bc]d
może się zdarzyć, że jest to nazwa istniejącego pliku, dlatego potencjalnie niebezpieczne jest używanie rzeczy takich jak rm -f ./*.[ch]
w tych powłokach i rm -f ./*.{c,h}
jest to mniejszy problem.
a{b,c}d
, gdy b
i c
części nie muszą być pojedyncze litery; np ex{ten,ci}sion
. Chociaż ex[tenci]sion
lub cokolwiek będzie pasować tylko do jednej z tych liter.
a[bc]d
jest zgodny ze wzorami i jest częścią standardu POSIX. W POSIX jest to wprowadzane jako „wyrażenie w nawiasie wzorcowym”. Jest to udokumentowane w sekcji 2.13 instrukcji
W przypadku cudzysłowu i poza wyrażeniem w nawiasie następujące trzy znaki mają specjalne znaczenie w specyfikacji wzorców:
?
Znak zapytania to wzór, który pasuje do dowolnego znaku.
*Gwiazdka to wzór, który powinien pasować do wielu znaków, jak opisano w Wzorach pasujących do wielu znaków.
[Otwarty nawias wprowadza wyrażenie w nawiasie wzorcowym.
Sekcja 2.13.3 wspomina także o tym, że zachowuje się inaczej niż można by się spodziewać po zwykłych wyrażeniach regularnych, gdy jest on używany do rozwijania nazw plików (moje podkreślenie)
Reguły opisane do tej pory w Wzorach pasujących do jednego znaku i Wzorach pasujących do wielu znaków są kwalifikowane według następujących reguł, które mają zastosowanie, gdy do interpretacji nazw plików używana jest notacja dopasowania wzorca:
Znak ukośnika w nazwie ścieżki musi być jednoznacznie dopasowany przy użyciu jednego lub więcej ukośników we wzorcu; nie mogą do niego pasować gwiazdki, znaki specjalne ani znaki zapytania ani wyrażenia w nawiasach. Cięcia we wzorcu muszą być identyfikowane przed wyrażeniami w nawiasach; dlatego ukośnik nie może być zawarty w wyrażeniu nawiasu wzorcowego używanym do rozwijania nazw plików. Jeżeli znak ukośnika zostanie znaleziony po znaku nieokreślonego otwartego nawiasu kwadratowego przed znalezieniem odpowiedniego zamykającego nawiasu kwadratowego, otwarty nawias będzie traktowany jak zwykły znak. Na przykład wzorzec
"a[b/c]d"
nie pasuje do takich ścieżek jakabd
luba/d
. Pasuje tylko do ścieżki dosłowniea[b/c]d
.
a{b,c}d
jest rozszerzeniem nawiasów klamrowych , nie znajduje się w specyfikacji POSIX. Oto odpowiednia część podręcznika bash (podkreślenie przeze mnie):
Rozwijanie nawiasów to mechanizm, za pomocą którego można generować dowolne ciągi . Ten mechanizm jest podobny do rozwijania nazw plików (patrz Rozszerzenie nazw plików), ale wygenerowane nazwy plików nie muszą istnieć . Wzory do rozszerzenia nawiasów klamrowych mają postać opcjonalnej preambuły, po której następuje seria ciągów oddzielonych przecinkami lub wyrażenie sekwencji między parą nawiasów klamrowych, a następnie opcjonalny postscriptum. Preambuła jest dodawana do każdego ciągu zawartego w nawiasach klamrowych, a następnie do każdego wynikowego łańcucha dołączany jest postscript, rozwijany od lewej do prawej.
Zgodnie z komentarzem @mosvy, ten pierwszy pojawił się z, csh
ale zachowanie w nim bash
jest inne csh
i inne powłoki. Ten typ rozszerzenia nawiasów jest również obecny w glob(3)
.
Istnieje inny rodzaj rozszerzenia nawiasów klamrowych, {a..z}
który pojawił się dopiero po wersji bash
3.0, a więcej dodano w wersji bash
4.0.
W powłoce, w której globbing jest włączony, wykonaj w pustym folderze, zwracany jest następujący wynik
$ echo a[bc]d
a[bc]d
$ echo a{b,c}d
abd acd
W odpowiedzi na komentarz @ Jesse_b, jeśli jesteś w interaktywnej powłoce i oba mają zastosowanie, a[bc]d
to mniej kłopotów z pisaniem. Na przykład grep pattern [ab][12].txt
.
csh
długo przedtem bash
. Jest także obecny w funkcji biblioteki glob (3). Różnica polega na tym, bash
że jest wykonywana przed innymi rozszerzeniami: a=A; ab=A/B; ac=A/C; echo $a{b,c}
będzie działać w bash inaczej niż jakakolwiek inna powłoka.
command a[bc]d
?