Разница между расширением и заменой в терминологии сценариев оболочки


8

Кажется, что расширение и замена взаимозаменяемы в одном и том же контексте в языке программирования оболочки. Например, некоторые документы, такие как справочное руководство Bash , Bash Hackers Wiki, используют слово «расширение» для объяснения « расширения параметров оболочки ». Однако некоторые другие документы, похоже, предпочитают слово «замена». Advanced Bash-Scripting Guide использует подстановку параметров .

Есть ли разница между «расширением» и «заменой» с точки зрения терминологии программирования оболочки?


Оба действуют в различных контекстах, например variable expansion, command substitution. В чем вы сомневаетесь?
devnull

Боюсь, что без конкретного контекста это слишком широко и неясно .
devnull

Если посмотреть на страницу руководства bash, то в общем случае слово «расширение», по-видимому, используется, если речь идет только о внутренней оболочке, тогда как «замена» представляется предпочтительной для вещей, связанных с внешними процессами.
celtschk

Если вы воспользуетесь моим советом, вы перестанете читать эти документы, пока не будете полностью знакомы с ними: pubs.opengroup.org/onlinepubs/9699919799/utilities/… Когда вы закончите с теми, кого вы делаете man shи man set. И когда у вас есть все это, вы делаете специфические для оболочки документы.
mikeserv

@devnull Вы правы. Хотя я поставил ссылку для контекста, было бы лучше указать контекст явно с вопросом. Я отредактирую вопрос так, чтобы люди могли понять это ясно.
MS.Kim

Ответы:


6

Подстановка почти синонимична расширению в этом контексте, потому что их значения перекрываются. Ни одна из них не является достаточно полной подкатегорией другой, хотя в разделе руководства GNU, на который вы ссылаетесь, есть замены, которые рассматриваются как часть общего расширения.

Расширение извлекает значение идентификатора. Например, если this=that, когда мы расширяемся, thisмы получаем that. Расширение, которое не включает подстановку, предопределено тем, что используемое значение уже существует и должно быть просто извлечено, хотя это включает в себя объединение извлеченных / явных значений (например, с «арифметическим расширением»).

Замещение создает значение как результат явной операции ввода / вывода. Например, если this=$(foo bar), thisявляется результатом выполнения foo barи захвата его вывода. 1 Хотя значение, полученное в результате подстановки, может быть полностью предсказуемым, оно отличается от значения, полученного при обычном расширении, поскольку оно фактически не существует до тех пор, пока не произойдет подстановка - оно произведено.

Замены бывают двух видов: команда и процесс , которые являются симметричными:

# Command substitution
foo=$(ls)
# Process substitution
wc <(ls)

«Команда» в первом - это ls, как и «процесс» во втором. Мы можем сказать, что то, что подставляется, на самом деле является концом трубы. Замена процесса перекрывается с перенаправлением . Тем не менее, это, пожалуй, слишком узкое техническое ограничение, которое подводит нас к сноске ...


  1. foo barв этом случае может быть внутренняя функция оболочки, и в этом случае отсутствует межпроцессный ввод-вывод. Существование встроенных оболочек менее очевидно скрывает эту разницу. С точки зрения содержания вход и выход будут одинаковыми.

Мне нравится это объяснение, но как бы это было в квадрате с расширением имени файла , которое, безусловно, создает набор имен файлов в результате операции (алгоритм сопоставления).
De Novo

Конечно, но для воспроизведения семантики разве «извлечение значения идентификатора» (то, что я назвал расширением) не является операцией, а следовательно, заменой? Тем более что «есть замены, которые считаются частью общего расширения». То есть связь между этими словами не аналогична разнице между левым и правым. Я думаю, что расширение имени файла хорошо соответствует моему первоначальному определению расширения, но я разъяснил материал о заменах выше, чтобы помочь сделать более очевидным, почему это не так.
Златовласка

Проблема, с которой я столкнулся при рассмотрении этого интуитивно понятного объяснения с расширением имени файла, заключалась не в том, что я хотел, чтобы термины определялись исключительно, а в том, что расширение имени файла, похоже, не возвращает значение, привязанное к идентификатору. Внутри данной оболочки значение для данного глоба будет зависеть не только от глоба, и один и тот же глоб может производить разные выходные данные в разных контекстах. Кроме того, нет необходимости связывать значение, чтобы получить его позже. Отношение не произвольное (как в foo = "все, что вы хотели бы"; echo "$ foo"), а скорее вычисление и результат.
De Novo

Я полагаю, что связь между выражением и значением в арифметическом расширении также не является (точно) произвольной, но для данного расширения определенно есть только одно значение, независимо от контекста. Я могу просто придираться, но из всех расширений оболочки расширение имени файла кажется странным человеком, учитывая это объяснение.
De Novo

2
set -- arg arg2
echo ${2+"$1"}
 #OUTPUT 
arg

shift
echo ${2+"$1"}
 #OUTPUT

 #there doesn't seem to be anything here

Я думаю, что разница, как правило, слишком минимальна, чтобы ее можно было заметить - и эти термины часто используются взаимозаменяемо. Хотя, если вы посмотрите на этих двух случаях, вы можете видеть , что в первом примере мы заменителя $1 для $2в результате расширения в $2. Как только $2невозможно расширить, нет замены.

Златовласка делает хорошее замечание о эфирном существовании замен. Вроде как кот Шредингера, наверное. Это напомнило мне о чем-то. Возможно, вы не знакомы с этой формой раскрытия параметров, указанной в POSIX, но она работает в некотором роде противоположной приведенной выше форме:

${var:?if $var is unset or null its \
     parent shell dies and this message is output to stderr}

Теперь иногда я хочу того же поведения, но за setценность. POSIX не определяет это поведение для чего-либо точно. Но с помощью хитрости или двух, это просто удалось:

N= #N is null
var="any value should fail"
${var:+${N:?we substitute our \$Null var when \$var is expanded}}
  #OUTPUT
sh: line 3: N: we substitute our $Null var when $var is expanded

Но:

N= #N is null
var=
${var:+${N:?is never substituted}}
  #OUTPUT

#there doesn't seem to be anything here
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.