Rozumiem, że jest to składnia podpowłoki. Czy (<commands...>)
to $()
tylko podpowłoka, z której można pobrać wartości zmiennych?
Uwaga: dotyczy to wersji bash 4.4 opartej na różnych sformułowaniach w ich dokumentacji.
Rozumiem, że jest to składnia podpowłoki. Czy (<commands...>)
to $()
tylko podpowłoka, z której można pobrać wartości zmiennych?
Uwaga: dotyczy to wersji bash 4.4 opartej na różnych sformułowaniach w ich dokumentacji.
Odpowiedzi:
$(…)
jest z definicji podpowłoką: jest kopią stanu środowiska wykonawczego powłoki¹, a zmiany stanu wprowadzone w podpowłoce nie mają wpływu na element nadrzędny. Podpowłoka jest zwykle implementowana przez rozwidlenie nowego procesu (ale niektóre powłoki mogą to zoptymalizować w niektórych przypadkach).
To nie jest podpowłoka, z której można pobierać wartości zmiennych. Gdyby zmiany zmiennych miały wpływ na element nadrzędny, nie byłby to podpowłoka. To podpowłoka, której dane wyjściowe rodzic może pobrać. Podkładka utworzona przez $(…)
ma swój standardowy wynik ustawiony na potok, a rodzic czyta z tego potoku i zbiera dane wyjściowe.
Istnieje kilka innych konstrukcji, które tworzą podpowłokę. Myślę, że to pełna lista bash:
( … )
tworzy tylko podpowłokę i czeka na jej zakończenie). Porównaj z tym, { … }
które grupy komendy służą wyłącznie celom składniowym i nie tworzą podpowłoki.… &
tworzy podpowłokę i nie czeka na jej zakończenie.… | …
tworzy dwie podpowłoki, jedną dla lewej i jedną dla prawej, i czeka na zakończenie obu. Powłoka tworzy potok i łączy standardowe wyjście po lewej stronie ze stroną zapisującą potoku, a standardowe wejście po prawej stronie do końca odczytu. W niektórych powłokach (ksh88, ksh93, zsh, bash z ustawioną i skuteczną lastpipe
opcją ) prawa strona działa w oryginalnej powłoce, więc konstrukcja potoku tworzy tylko jedną podpowłokę.$(…)
(również pisane `…`
) tworzy podpowłokę ze standardowym wyjściem ustawionym na potok, zbiera dane wyjściowe w obiekcie nadrzędnym i rozwija się do tego wyniku, pomijając jego końcowe znaki. (I wyniki mogą być dalej przedmiotem podziału i globowania, ale to inna historia.)<(…)
tworzy podpowłokę ze standardowym wyjściem ustawionym na potok i rozwija się do nazwy potoku. Element nadrzędny (lub inny proces) może otworzyć potok w celu komunikacji z podpowłoką. >(…)
robi to samo, ale z potokiem na standardowym wejściu.coproc …
tworzy podpowłokę i nie czeka na jej zakończenie. Standardowe dane wejściowe i wyjściowe podpowłoki są ustawione na potok, a element nadrzędny jest podłączony do drugiego końca każdego potoku.${...}
do odpowiedzi?
command | { read line; … }
(w zależności od powłoki, line
może, ale nie musi być jeszcze dostępny po potoku). Wszystkie sposoby obejmują podpowłokę, ponieważ polecenie generujące dane wyjściowe musi być uruchamiane niezależnie od powłoki, która odczytuje dane wejściowe. Jeśli polecenie jest czysto wewnętrzne względem powłoki (tylko konstrukcja i wbudowane powłoki, brak poleceń zewnętrznych), powłoka może nie utworzyć podprocesu, ale jest to tylko optymalizacja, nadal tworzy podpowłokę.
Ze strony podręcznika bash (1) w wersji bash 4.4, sekcja „EXPANSION”, podsekcja „Command Substitution”:
Bash wykonuje ekspansję, wykonując
command
w środowisku podpowłoki [...]
bash
nie wspomina o żadnej podpowłoce: Bash performs the expansion by executing command and replacing the command substitution with the standard output of the command, with any trailing newlines deleted.
Zastanawiam się, czy było to celowe pominięcie.