Czy $ () jest podpowłoką?


Odpowiedzi:


75

$(…)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:

  • Podkładka do grupowania : ( … )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.
  • Tło : … &tworzy podpowłokę i nie czeka na jej zakończenie.
  • Rurociąg : … | …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ą lastpipeopcją ) prawa strona działa w oryginalnej powłoce, więc konstrukcja potoku tworzy tylko jedną podpowłokę.
  • Podstawianie poleceń : $(…)(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.)
  • Podstawienie procesu : <(…)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.
  • Coprocess : 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.

¹ W przeciwieństwie do uruchamiania osobnej powłoki .


Czy możesz również dołączyć ${...}do odpowiedzi?
user1717828,

3
@ user1717828 Co? Dlaczego? Co zdalna ekspansja zmienna ma wspólnego z tym pytaniem? W odpowiedzi nie zamierzam zawrzeć całej instrukcji obsługi powłoki.
Gilles „SO- przestań być zły”

1
Co zdalna ekspansja zmienna ma wspólnego z tym pytaniem? Nie wiem, dlatego zapytałem :-) Zgaduję, że podstawienie nawiasów klamrowych nie przypomina podmiany nawiasów klamrowych.
user1717828,

@ user1717828: rozwijanie zmiennych nie jest powiązane z podpowłokami; jest to zupełnie odrębny mechanizm i na pewno warto go przeczytać, jeśli dopiero zaczynasz!
0xdd

1
@EnricoMariaDeAngelis To nie jedyny sposób, ale najbardziej naturalny. Innym sposobem jest command | { read line; … }(w zależności od powłoki, linemoż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ę.
Gilles „SO- przestań być zły”

20

Ze strony podręcznika bash (1) w wersji bash 4.4, sekcja „EXPANSION”, podsekcja „Command Substitution”:

Bash wykonuje ekspansję, wykonując commandw środowisku podpowłoki [...]



1
Co ciekawe, pod CentOS 7 strona bashnie 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.
dr01

6
@ dr01 Wręcz przeciwnie, bash 4.4 zmienił brzmienie tego zdania, tak aby zawierało słowo „podpowłoka”. To było wyjaśnienie: w instrukcji wyraźnie wspomniano, że różne inne konstrukcje były podpowłokami, ale do 4.4 nie było wyraźnie powiedziane o zastępowaniu poleceń.
Gilles „SO- przestań być zły”

Tak, na CentOS v7.4.1708 (dość niedawno) bash to v4.2.46.
dr01

5

Tak, ( commands... )jest bashpodpowłoką, która zostanie wykonana commands...w innym procesie.

Jedyną różnicą, jaką masz, $( commands... )jest to, że ta część kodu po wykonaniu commands...zostanie zastąpiona wszystkim, co commands...napisałem stdout.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.