$(…)по определению является подоболочкой: это копия состояния времени выполнения оболочки¹, и изменения состояния, внесенные в подоболочку, не влияют на родительский объект. Подоболочка обычно реализуется путем разветвления нового процесса (но некоторые оболочки могут оптимизировать это в некоторых случаях).
Это не подоболочка, из которой вы можете получить значения переменных. Если бы изменения в переменных оказали влияние на родителя, это не было бы подоболочкой. Это подоболочка, чей вывод может извлечь родитель. Для подоболочки, созданной с помощью $(…)стандартного вывода, задан канал, а родительский объект читает из этого канала и собирает выходные данные.
Есть несколько других конструкций, которые создают подоболочку. Я думаю, что это полный список для Bash:
Подоболочка для группировки : ( … )ничего не делает, кроме как создает подоболочку и ожидает ее завершения). Сравните с тем, { … }какие группы команд чисто для синтаксических целей и не создает подоболочки.
Фон : … &создает подоболочку и не ожидает его завершения.
Конвейер : … | …создает две подоболочки, одну для левой стороны и одну для правой стороны, и ожидает завершения обоих. Оболочка создает канал и соединяет стандартный вывод левой стороны с концом записи канала, а стандартный ввод правой стороны - с концом чтения. В некоторых оболочках (ksh88, ksh93, zsh, bash с установленной и действующей lastpipeопцией ) правая часть выполняется в исходной оболочке, поэтому конструкция конвейера создает только одну подоболочку.
Подстановка команд : $(…)(также пишется `…`) создает подоболочку со стандартным выводом, установленным для канала, собирает выходные данные в родительском и расширяется до этого вывода, минуя завершающие символы новой строки. (И результат может быть далее подвергнут расщеплению и смещению, но это другая история.)
Подстановка процесса : <(…)создает подоболочку со стандартным выводом, установленным в канал, и расширяется до имени канала. Родитель (или какой-то другой процесс) может открыть канал для связи с подоболочкой. >(…)делает то же самое, но с трубкой на стандартном вводе.
Копроцесс : coproc …создает подоболочку и не ждет его завершения. Каждый стандартный вход и выход подоболочки настроен на канал, родительский элемент которого подключен к другому концу каждого канала.
@ user1717828 Что? Почему? Какое отношение имеет расширение переменных к этому вопросу? Я не собираюсь включать полное руководство по оболочке в мой ответ.
Жиль "ТАК - перестань быть злым"
1
Какое отношение имеет расширение переменных к этому вопросу? Я не знаю, вот почему я спросил :-) Так что я предполагаю, что замена фигурных скобок не похожа на замену скобок в скобках.
user1717828
@ user1717828: расширение переменной не связано с подоболочками; это вообще отдельный механизм, и его обязательно стоит прочитать, если вы только начинаете!
0xdd
1
@EnricoMariaDeAngelis Это не единственный способ, но это самый естественный способ. Другой способ command | { read line; … }(в зависимости от оболочки, lineможет или не может быть доступен после конвейера). Все способы включают в себя подоболочку, потому что команда, которая производит вывод, должна выполняться независимо от оболочки, которая читает ввод. Если команда является чисто внутренней по отношению к оболочке (только конструкции оболочки и встроенные функции, а не внешние команды), оболочка может не создавать подпроцесс, но это всего лишь оптимизация, она по-прежнему создает подоболочку.
Жиль "ТАК - прекрати быть злым"
20
Из справочной страницы bash (1) в bash версии 4.4, раздел «РАСШИРЕНИЕ», подраздел «Подстановка команд»:
Bash выполняет расширение, выполняя commandв среде подоболочки [...]
Интересно, что под CentOS 7 на bashman-странице не упоминается какая-либо подоболочка: Bash performs the expansion by executing command and replacing the command substitution with the standard output of the command, with any trailing newlines deleted.интересно, было ли это намеренным упущением.
Dr01
6
@ dr01 Напротив, bash 4.4 изменил формулировку этого предложения, добавив слово «подоболочка». Это было разъяснение: в руководстве явно упоминалось, что различные другие конструкции были подоболочками, но до 4.4 это явно не указывалось для подстановки команд.
Жиль "ТАК - перестань быть злым"
Да, в CentOS v7.4.1708 (сравнительно недавно) bash - v4.2.46.
dr01
5
Да, ( commands... )это bashподоболочка, которая будет выполняться commands...в другом процессе.
Единственное отличие, которое у вас есть, $( commands... )заключается в том, что эта часть кода после выполнения commands...будет заменена всем, что commands...написано stdout.
Ответы:
$(…)
по определению является подоболочкой: это копия состояния времени выполнения оболочки¹, и изменения состояния, внесенные в подоболочку, не влияют на родительский объект. Подоболочка обычно реализуется путем разветвления нового процесса (но некоторые оболочки могут оптимизировать это в некоторых случаях).Это не подоболочка, из которой вы можете получить значения переменных. Если бы изменения в переменных оказали влияние на родителя, это не было бы подоболочкой. Это подоболочка, чей вывод может извлечь родитель. Для подоболочки, созданной с помощью
$(…)
стандартного вывода, задан канал, а родительский объект читает из этого канала и собирает выходные данные.Есть несколько других конструкций, которые создают подоболочку. Я думаю, что это полный список для Bash:
( … )
ничего не делает, кроме как создает подоболочку и ожидает ее завершения). Сравните с тем,{ … }
какие группы команд чисто для синтаксических целей и не создает подоболочки.… &
создает подоболочку и не ожидает его завершения.… | …
создает две подоболочки, одну для левой стороны и одну для правой стороны, и ожидает завершения обоих. Оболочка создает канал и соединяет стандартный вывод левой стороны с концом записи канала, а стандартный ввод правой стороны - с концом чтения. В некоторых оболочках (ksh88, ksh93, zsh, bash с установленной и действующейlastpipe
опцией ) правая часть выполняется в исходной оболочке, поэтому конструкция конвейера создает только одну подоболочку.$(…)
(также пишется`…`
) создает подоболочку со стандартным выводом, установленным для канала, собирает выходные данные в родительском и расширяется до этого вывода, минуя завершающие символы новой строки. (И результат может быть далее подвергнут расщеплению и смещению, но это другая история.)<(…)
создает подоболочку со стандартным выводом, установленным в канал, и расширяется до имени канала. Родитель (или какой-то другой процесс) может открыть канал для связи с подоболочкой.>(…)
делает то же самое, но с трубкой на стандартном вводе.coproc …
создает подоболочку и не ждет его завершения. Каждый стандартный вход и выход подоболочки настроен на канал, родительский элемент которого подключен к другому концу каждого канала.¹ В отличие от запуска отдельной оболочки .
источник
${...}
в ответ?command | { read line; … }
(в зависимости от оболочки,line
может или не может быть доступен после конвейера). Все способы включают в себя подоболочку, потому что команда, которая производит вывод, должна выполняться независимо от оболочки, которая читает ввод. Если команда является чисто внутренней по отношению к оболочке (только конструкции оболочки и встроенные функции, а не внешние команды), оболочка может не создавать подпроцесс, но это всего лишь оптимизация, она по-прежнему создает подоболочку.Из справочной страницы bash (1) в bash версии 4.4, раздел «РАСШИРЕНИЕ», подраздел «Подстановка команд»:
источник
bash
man-странице не упоминается какая-либо подоболочка:Bash performs the expansion by executing command and replacing the command substitution with the standard output of the command, with any trailing newlines deleted.
интересно, было ли это намеренным упущением.Да,
( commands... )
этоbash
подоболочка, которая будет выполнятьсяcommands...
в другом процессе.Единственное отличие, которое у вас есть,
$( commands... )
заключается в том, что эта часть кода после выполненияcommands...
будет заменена всем, чтоcommands...
написаноstdout
.источник