Rozszerzenie zmiennej powłoki i wpływ glob i split na nią

18

Ten post zawiera dwa osobne pytania, ale myślę, że zgrupowanie ich da więcej kontekstu. Przeszedłem przez to pytanie dotyczące cytatów wokół zmiennych, ale nie do końca rozumiem, co oznacza ekspansja zmiennych . Moje pierwsze pytanie brzmi:

  1. Czym jest zmienna ekspansja w systemach Unix / Linux?

Druga część mojego pytania dotyczy następujących terminów:

  1. glob
  2. rozdzielać

Co oznaczają powyższe i jak wpływają one na zmienną ekspansję? Odpowiedź na pierwotne pytanie wymienia następujące:

Pomyśl o braku cudzysłowów (w kontekście list) jako o operatorze split + glob.

Jakby test echa $ był globalnym echem (split („$ test”)).

Nie mogłem znaleźć odpowiedzi, które bezpośrednio dotyczą koncepcji globowania i dzielenia, ale raczej używam tych terminów bezpośrednio w odpowiedziach na inne pytania, takie jak to ostatnie .

Maniak
źródło

Odpowiedzi:

15

Rozszerzanie zmiennych (standardowym terminem jest rozszerzanie parametrów , a czasem nazywane jest również podstawieniem zmiennych ) w zasadzie oznacza zastąpienie zmiennej jej wartością. Dokładniej, oznacza to zastąpienie $VARIABLEkonstrukt (lub ${VARIABLE}lub ${VARIABLE#TEXT}lub inne konstrukty) za pośrednictwem innego tekstu, który jest zbudowany z wartości zmiennej. Ten drugi tekst jest rozwinięciem zmiennej.

Proces ekspansji przebiega następująco. (Omawiam tylko typowy przypadek, niektóre ustawienia powłoki i rozszerzenia modyfikują zachowanie).

  1. Weź wartość zmiennej, która jest łańcuchem. Jeśli zmienna nie jest zdefiniowana, użyj pustego ciągu.
  2. Jeśli konstrukcja zawiera transformację, zastosuj ją. Na przykład, jeśli konstrukcja jest ${VARIABLE#TEXT}, a wartość zmiennej zaczyna się od TEXT, usuń TEXTz początku wartości.
  3. Jeśli kontekst wymaga pojedynczego słowa (na przykład w podwójnych cudzysłowach, w prawej części zadania lub w dokumencie tutaj), zatrzymaj się tutaj. W przeciwnym razie przejdź do kolejnych kroków.
  4. Podziel wartość na osobne słowa w każdej sekwencji białych znaków. (Zmienną IFSmożna zmienić tak, aby dzieliła się na znaki inne niż białe znaki). W rezultacie nie jest to już ciąg, ale lista ciągów. Ta lista może być pusta, jeśli wartość zawiera tylko białe znaki.
  5. Traktuj każdy element listy jako wzór wieloznaczny nazwy pliku, tj . Glob . Jeśli wzorzec pasuje do niektórych plików, jest zastępowany przez listę pasujących nazw plików, w przeciwnym razie pozostaje sam.

Załóżmy na przykład, że zmienna foozawiera a* b* c*a bieżący katalog zawiera pliki bar, baza paz. Następnie ${foo#??}jest rozwijany w następujący sposób:

  1. Wartość zmiennej to ciąg 8 znaków a* b* c*.
  2. #??oznacza usunięcie dwóch pierwszych znaków, co daje ciąg 6 znaków  b* c*(ze spacją początkową).
  3. Jeśli rozwinięcie odbywa się w kontekście listy (tj. Nie w podwójnych cudzysłowach lub w innym podobnym kontekście), kontynuuj.
  4. Podziel ciąg na słowa oddzielone spacjami, w wyniku czego powstanie lista dwóch ciągów: b*i c*.
  5. Ciąg b*interpretowany jako wzór pasuje do dwóch plików: bari baz. Ciąg c*nie pasuje do żadnego pliku, więc jest pozostawiony samemu sobie. Rezultatem jest lista trzech ciągów: bar, baz, c*.

Na przykład echo ${foo#??}wypisuje bar baz c*(polecenie echołączy swoje argumenty ze spacją między nimi).

Aby uzyskać więcej informacji, zobacz:

Gilles „SO- przestań być zły”
źródło
2
Zauważ, że to się nazywa ekspansja parametr , ponieważ odnosi się do zmiennych ( $var) i innych typów parametrów, takich jak $1, $#, $?, $-...
Stéphane Chazelas
12

glob / split

Najpierw wezmę glob / split. @ Odpowiedź Stephane'a, do której linkujesz, używa tych terminów w ogólnym znaczeniu. Nie są to rzeczywiste polecenia ani nic w tym rodzaju, tylko pseudo operacje.

split("$test")By podzielić zawartość „$ test” w górę „do tablicy” elementów.

glob(...)By następnie zająć się rozwijać każdy z tych elementów, które zawierają powłoki globbing znaki takie jak *lub zakresy [1-2].

Przykład

Powiedzmy, że nasz ciąg $testjest następujący.

$ test="afile[1-2] afile[3-5]"

Powiedzmy też, że mamy katalog z niektórymi plikami.

$ ls -1
afile1
afile2
afile3
afile4
afile5

Teraz, jeśli spróbujemy powtórzyć go bez cudzysłowów, powinieneś zauważyć, że nasz ciąg został podzielony na spacje, a następnie wszystkie globbingowe znaki zostały rozwinięte.

$ echo $test
afile1 afile2 afile3 afile4 afile5

Gdybyśmy jednak zacytowali zmienną, gdy przekazaliśmy ją jako argument echo, otrzymalibyśmy oryginalny ciąg literału.

$ echo "$test"
afile[1-2] afile[3-5]

zmienna ekspansja

Termin ekspansja zmiennej ma obejmować podstawową operację wykonywaną przez powłokę w ramach jej podstawowych operacji. Powłoka jest odpowiedzialna za parsowanie danych wejściowych, a następnie wykonanie tych danych wejściowych, gdy zostanie uznana za poprawną składniowo.

W naszym poprzednim przykładzie. Kiedy zmienna $testbyła prezentowana bez echocudzysłowu, mówiliśmy powłoce, aby poszła naprzód i podzieliła te argumenty, a następnie je zsumowała.

Kiedy był cytowany, zasadniczo wyłączaliśmy tę funkcję za pomocą tego, co kiedykolwiek zmienne zawarliśmy podwójnymi cudzysłowami.

Przykład

Oto kilka dodatkowych przykładów globowania i podziału.

glob / dzielenie odbywa się automatycznie

$ echo file{1..3}
file1 file2 file3

$ echo file{1..3} dir{a..b}
file1 file2 file3 dira dirb

$ echo dir{z..w} file{A..D}
dirz diry dirx dirw fileA fileB fileC fileD

$ echo dir{z..w} file{A..B} fileC
dirz diry dirx dirw fileA fileB fileC

glob / dzielenie wyłączone przez podwójne cytowanie

$ echo "dir{z..w} file{A..B} fileC"
dir{z..w} file{A..B} fileC

$ echo "dir{z..w} file{A..B}"
dir{z..w} file{A..B}
slm
źródło
Nie wiedziałem, że zakresy również działają w odwrotnej kolejności.
Joe