Является ли $ () подоболочкой?

51

Я понимаю, что синтаксис подоболочки (<commands...>)- это $()всего лишь подоболочка, из которой можно извлечь значения переменных?

Примечание: это относится к bash 4.4 на основании различных формулировок в их документации.

leeand00
источник
4
Возможный дубликат Что такое подстановка команд в оболочке?
Жюльен Лопес

Ответы:

75

$(…)по определению является подоболочкой: это копия состояния времени выполнения оболочки¹, и изменения состояния, внесенные в подоболочку, не влияют на родительский объект. Подоболочка обычно реализуется путем разветвления нового процесса (но некоторые оболочки могут оптимизировать это в некоторых случаях).

Это не подоболочка, из которой вы можете получить значения переменных. Если бы изменения в переменных оказали влияние на родителя, это не было бы подоболочкой. Это подоболочка, чей вывод может извлечь родитель. Для подоболочки, созданной с помощью $(…)стандартного вывода, задан канал, а родительский объект читает из этого канала и собирает выходные данные.

Есть несколько других конструкций, которые создают подоболочку. Я думаю, что это полный список для Bash:

  • Подоболочка для группировки : ( … )ничего не делает, кроме как создает подоболочку и ожидает ее завершения). Сравните с тем, { … }какие группы команд чисто для синтаксических целей и не создает подоболочки.
  • Фон : … &создает подоболочку и не ожидает его завершения.
  • Конвейер : … | …создает две подоболочки, одну для левой стороны и одну для правой стороны, и ожидает завершения обоих. Оболочка создает канал и соединяет стандартный вывод левой стороны с концом записи канала, а стандартный ввод правой стороны - с концом чтения. В некоторых оболочках (ksh88, ksh93, zsh, bash с установленной и действующей lastpipeопцией ) правая часть выполняется в исходной оболочке, поэтому конструкция конвейера создает только одну подоболочку.
  • Подстановка команд : $(…)(также пишется `…`) создает подоболочку со стандартным выводом, установленным для канала, собирает выходные данные в родительском и расширяется до этого вывода, минуя завершающие символы новой строки. (И результат может быть далее подвергнут расщеплению и смещению, но это другая история.)
  • Подстановка процесса : <(…)создает подоболочку со стандартным выводом, установленным в канал, и расширяется до имени канала. Родитель (или какой-то другой процесс) может открыть канал для связи с подоболочкой. >(…)делает то же самое, но с трубкой на стандартном вводе.
  • Копроцесс : coproc …создает подоболочку и не ждет его завершения. Каждый стандартный вход и выход подоболочки настроен на канал, родительский элемент которого подключен к другому концу каждого канала.

¹ В отличие от запуска отдельной оболочки .

Жиль "ТАК - перестань быть злым"
источник
Не могли бы вы также включить ${...}в ответ?
user1717828
3
@ user1717828 Что? Почему? Какое отношение имеет расширение переменных к этому вопросу? Я не собираюсь включать полное руководство по оболочке в мой ответ.
Жиль "ТАК - перестань быть злым"
1
Какое отношение имеет расширение переменных к этому вопросу? Я не знаю, вот почему я спросил :-) Так что я предполагаю, что замена фигурных скобок не похожа на замену скобок в скобках.
user1717828
@ user1717828: расширение переменной не связано с подоболочками; это вообще отдельный механизм, и его обязательно стоит прочитать, если вы только начинаете!
0xdd
1
@EnricoMariaDeAngelis Это не единственный способ, но это самый естественный способ. Другой способ command | { read line; … }(в зависимости от оболочки, lineможет или не может быть доступен после конвейера). Все способы включают в себя подоболочку, потому что команда, которая производит вывод, должна выполняться независимо от оболочки, которая читает ввод. Если команда является чисто внутренней по отношению к оболочке (только конструкции оболочки и встроенные функции, а не внешние команды), оболочка может не создавать подпроцесс, но это всего лишь оптимизация, она по-прежнему создает подоболочку.
Жиль "ТАК - прекрати быть злым"
20

Из справочной страницы bash (1) в bash версии 4.4, раздел «РАСШИРЕНИЕ», подраздел «Подстановка команд»:

Bash выполняет расширение, выполняя commandв среде подоболочки [...]

Игнасио Васкес-Абрамс
источник
9
Это также явно указано в POSIX .
Стивен Китт
1
Интересно, что под 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.

Искуство
источник