Jaka jest różnica między `a [bc] d` (nawiasy kwadratowe) a` a {b, c} d` (nawiasy klamrowe)?

28

Jaka jest różnica między a[bc]di a{b,c}d? Dlaczego ludzie używają, a{b,c}dgdy już jest a[bc]d?

Weijun Zhou
źródło
Kto ci kazał użyć command a[bc]d?
Jesse_b
3
Z pewnością ma swoje zastosowanie, jeśli się go dobrze zrozumie.
Weijun Zhou
7
Chyba po prostu nie rozumiem, jak doszło do zamieszania między nimi.
Jesse_b
Zostałem wyraźnie zapytany przez współpracownika mniej znającego się na Linuksie, chociaż nie ostatnio.
Weijun Zhou
@Jesse_b Jeśli kiedykolwiek spróbujesz ich z operacjami na plikach takich jak lsi kiedykolwiek spróbujesz tylko pojedynczych znaków, będą one wyglądać tak samo.
Nacht - Przywróć Monikę

Odpowiedzi:

43

Te dwa są całkiem różne.

a[bc]dto wzorzec nazwy pliku (w powłokach innych niż fish). Rozwinie się do dwóch nazw plików abd i acdjeś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 ai dw pliku musi być albo balbo c.

  • Jeśli abdistnieje, ale acdnie istnieje, rozszerzyłby się tylko abdi odwrotnie.

  • Jeśli nie abd, nie acdistnieją, 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 nullglobniektóre starsze wersje fishoryginalnego Uniksa shi (t)cshjeśli w tym samym poleceniu są inne pasujące globusy).

a{b,c}djest 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..klub 20..25lub więcej zaawansowanych, jak 00..20..2i 0..20..2%02d) i rozszerzenie jest obliczana przez łączenie każdego z tych łańcuchów z flankującymi ciągi ai 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]dmoż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.

Kusalananda
źródło
Dziękujemy za wyjaśnienie: „Jeśli abd istnieje, ale acd nie, to rozwinąłby się tylko do abd”. Myślę, że tego brakuje w mojej odpowiedzi.
Weijun Zhou
9
Inną kluczową różnicą jest to, że a{b,c}d, gdy bi cczęści nie muszą być pojedyncze litery; np ex{ten,ci}sion. Chociaż ex[tenci]sionlub cokolwiek będzie pasować tylko do jednej z tych liter.
Alexis
7

a[bc]djest 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 jak abdlub a/d. Pasuje tylko do ścieżki dosłownie a[b/c]d.

a{b,c}djest 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, cshale zachowanie w nim bashjest inne cshi 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 bash3.0, a więcej dodano w wersji bash4.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]dto mniej kłopotów z pisaniem. Na przykład grep pattern [ab][12].txt.

Weijun Zhou
źródło
2
Rozszerzenie nawiasu klamrowego nie jest „baszizmem”; po raz pierwszy pojawił się na cshdł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.
mosvy
Dziękuję Ci. Zaktualizuję odpowiedź.
Weijun Zhou