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 $
?
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 $
?
Odpowiedzi:
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
, bash
itd., A zsh
takż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 basedir
otrzyma wartość /usr/local/bin
.
Lub w Cygwin:
$ bash c:\\Users\\Me\\script.sh
wtedy basedir
otrzyma 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ść $0
to c:\Users\Me\script.sh
.
Innym sposobem robi to samo bez używania dirname
, echo
i sed
byłoby
basedir="${0//\\//}"
basedir="${basedir%/*}"
/bin/sh
Solaris 10 lub wcześniejsza) nie obsługiwała $(...)
.
varible=$(..)
Nazywa podstawienie poleceń i to nie oznacza nic więcej, ale aby uruchomić polecenie powłoki i przechowywać swoje wyjście do zmiennej lub wyświetlanie z powrotem za pomocą polecenia echo. Na przykład wyświetl datę i godzinę:
echo "Today is $(date)"
i do przechowywania w zmiennej:
SERVERNAME=$(hostname)
Aby uzyskać więcej informacji: https://www.cyberciti.biz/faq/unix-linux-bsd-appleosx-bash-assign-variable-command-output/
man bash