Co to jest zmienna formularza = $ (…)

9

Co to znaczy:

basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

Jestem szczególnie zainteresowany tą częścią:

varible=$(...)

Wiem, że w celu wykonania podprocesu używane są nawiasy, ale co, jeśli zostaną użyte razem z $?

Max Koretskyi
źródło
3
Jeśli używasz bash: man bash
zajrzyj na

Odpowiedzi:

16

Z podręcznika Bash ( man bash):

   Zmiana polecenia
       Podstawienie polecenia pozwala na wyjście polecenia zastępującego
       nazwa polecenia. Istnieją dwie formy:

              $ (polecenie)
       lub
              „polecenie”

       Bash wykonuje rozwinięcie, wykonując polecenie w podpowłoce
       środowisko i zastąpienie podstawienia polecenia standardem
       wyjście polecenia, z usuniętymi końcowymi znakami nowej linii. Osadzone
       znaki nowego wiersza nie są usuwane, ale mogą zostać usunięte podczas słowa
       rozdzielać. Podstawienie polecenia $ (plik cat) można zastąpić przez
       równoważny, ale szybszy $ (<plik).

(Odnosi się to do wszystkich Bourne'a jak muszle, czyli sh, ksh, zsh, bashitd., A zshtakże możliwość przechwytywania danych z osadzonymi znakami NUL w ten sposób)

Komenda

basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

przypisze nazwę katalogu, w którym znajduje się skrypt (jednocześnie zmieniając wszystkie ukośniki odwrotne na ukośniki) do zmiennej basedir. Wszelkie błędy, ostrzeżenia lub inne komunikaty diagnostyczne, które są wysyłane do standardowego strumienia błędów, będą nadal wyświetlane na terminalu ( $(...)przechwytuje tylko standardowe wyjście polecenia).

Powłoka rozpocznie się od wykonania najbardziej wewnętrznej zamiany poleceń:

echo "$0" | sed -e 's,\\,/,g'

Dane wyjściowe zostaną podane jako ciąg znaków dirname, a dane wyjściowe zostaną przypisane do zmiennej basedir.

Podwójne cudzysłowy mają na celu upewnienie się, że nie zostanie wykonane dzielenie słów ani dzielenie nazw plików, w przeciwnym razie może się okazać, że skrypt zawiedzie lub wygenerować dziwny wynik, gdy $0(nazwa skryptu wraz ze ścieżką użytą do jego wykonania) zawiera spację znak lub znak globowania nazwy pliku (taki jak ?lub *).

Zasadniczo dobrym pomysłem jest zawsze cytowanie rozszerzeń (rozszerzenia zmienne, podstawienia poleceń i rozszerzenia arytmetyczne). Zobacz to pytanie i odpowiedzi, aby uzyskać doskonałe wyjaśnienie, dlaczego jest to dobry pomysł.

Jeśli skrypt został wykonany jako

$ /usr/local/bin/script.sh

wtedy basedirotrzyma wartość /usr/local/bin.

Lub w Cygwin:

$ bash c:\\Users\\Me\\script.sh

wtedy basedirotrzyma wartość c:/Users/Me. Podwójne odwrotne ukośniki w wierszu poleceń w tym przypadku służą tylko do ucieczki przed pojedynczymi odwrotnymi ukośnikami z powłoki. Rzeczywista wartość $0to c:\Users\Me\script.sh.

Innym sposobem robi to samo bez używania dirname, echoi sedbyłoby

basedir="${0//\\//}"
basedir="${basedir%/*}"
Kusalananda
źródło
dzięki, więc w zasadzie zaczyna się parsowanie od najgłębszego nawiasu, prawda? i dlaczego używane są cytaty?
Max Koretskyi
@Maksymus Prawidłowo. Zaktualizowałem odpowiedź o dalsze informacje.
Kusalananda
Może powinieneś powiedzieć „dotyczy wszystkich pocisków podobnych do Bourne'a”. Trochę jaśniej w ten sposób
Sergiy Kolodyazhnyy
@Serg, zauważ, że powłoka Bourne'a (podobnie jak /bin/shSolaris 10 lub wcześniejsza) nie obsługiwała $(...).
Stéphane Chazelas
@ StéphaneChazelas Włączę to.
Kusalananda
6

Oznacza to uruchomienie tego, co jest w nawiasach w podpowłoce i zwrócenie tego jako wartości , w twoim przypadku przypisanie tego do varible.

Marc
źródło