Я понимаю, что синтаксис подоболочки (<commands...>)
- это $()
всего лишь подоболочка, из которой можно извлечь значения переменных?
Примечание: это относится к bash 4.4 на основании различных формулировок в их документации.
Я понимаю, что синтаксис подоболочки (<commands...>)
- это $()
всего лишь подоболочка, из которой можно извлечь значения переменных?
Примечание: это относится к bash 4.4 на основании различных формулировок в их документации.
Ответы:
$(…)
по определению является подоболочкой: это копия состояния времени выполнения оболочки¹, и изменения состояния, внесенные в подоболочку, не влияют на родительский объект. Подоболочка обычно реализуется путем разветвления нового процесса (но некоторые оболочки могут оптимизировать это в некоторых случаях).
Это не подоболочка, из которой вы можете получить значения переменных. Если бы изменения в переменных оказали влияние на родителя, это не было бы подоболочкой. Это подоболочка, чей вывод может извлечь родитель. Для подоболочки, созданной с помощью $(…)
стандартного вывода, задан канал, а родительский объект читает из этого канала и собирает выходные данные.
Есть несколько других конструкций, которые создают подоболочку. Я думаю, что это полный список для Bash:
( … )
ничего не делает, кроме как создает подоболочку и ожидает ее завершения). Сравните с тем, { … }
какие группы команд чисто для синтаксических целей и не создает подоболочки.… &
создает подоболочку и не ожидает его завершения.… | …
создает две подоболочки, одну для левой стороны и одну для правой стороны, и ожидает завершения обоих. Оболочка создает канал и соединяет стандартный вывод левой стороны с концом записи канала, а стандартный ввод правой стороны - с концом чтения. В некоторых оболочках (ksh88, ksh93, zsh, bash с установленной и действующей lastpipe
опцией ) правая часть выполняется в исходной оболочке, поэтому конструкция конвейера создает только одну подоболочку.$(…)
(также пишется `…`
) создает подоболочку со стандартным выводом, установленным для канала, собирает выходные данные в родительском и расширяется до этого вывода, минуя завершающие символы новой строки. (И результат может быть далее подвергнут расщеплению и смещению, но это другая история.)<(…)
создает подоболочку со стандартным выводом, установленным в канал, и расширяется до имени канала. Родитель (или какой-то другой процесс) может открыть канал для связи с подоболочкой. >(…)
делает то же самое, но с трубкой на стандартном вводе.coproc …
создает подоболочку и не ждет его завершения. Каждый стандартный вход и выход подоболочки настроен на канал, родительский элемент которого подключен к другому концу каждого канала.${...}
в ответ?
command | { read line; … }
(в зависимости от оболочки, line
может или не может быть доступен после конвейера). Все способы включают в себя подоболочку, потому что команда, которая производит вывод, должна выполняться независимо от оболочки, которая читает ввод. Если команда является чисто внутренней по отношению к оболочке (только конструкции оболочки и встроенные функции, а не внешние команды), оболочка может не создавать подпроцесс, но это всего лишь оптимизация, она по-прежнему создает подоболочку.
Из справочной страницы bash (1) в bash версии 4.4, раздел «РАСШИРЕНИЕ», подраздел «Подстановка команд»:
Bash выполняет расширение, выполняя
command
в среде подоболочки [...]
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.
интересно, было ли это намеренным упущением.