shell 脚本术语中的扩展和替换之间的区别

shell 脚本术语中的扩展和替换之间的区别

扩张代换在 shell 编程语言的相同上下文中似乎可以互换。例如,一些文档,例如Bash 参考手册,Bash 黑客维基用“扩展”这个词来解释“shell参数”扩张'。然而,其他一些文件似乎更喜欢“替代”这个词。高级 Bash 脚本指南使用参数替代

就 shell 编程术语而言,“扩展”和“替换”之间有什么区别吗?

答案1

代换几乎是同义词扩张在这种情况下,因为它们的含义重叠。两者都不是另一个的完整子类别,尽管在GNU手册您引用的部分中有一些替换被视为整体扩展的一部分。

一个扩张正在提取标识符的值。例如,如果this=that,当我们展开时this我们得到that。不涉及替换的扩展是预先确定的,因为所使用的值已经存在并且必须简单地是检索到,尽管这包括组合检索/显式值(例如“算术扩展”)。

A代换创建一个值作为显式输入/输出操作的结果。例如, ifthis=$(foo bar)是执行并捕获其输出this的结果。 1虽然替换产生的值可能是完全可预测的,但它与正常扩展中检索到的值不同,因为在替换发生之前它实际上并不存在 - 它是foo bar产生的。

替代品有两种口味,命令过程,它们有点对称:

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

第一个中的“命令”是ls,第二个中的“进程”也是。我们可能会说被替换的实际上是管道的末端。流程替代重叠重定向。然而,这在技术上可能有点过于严格,这让我们看到脚注......


  1. foo bar在这种情况下可能是一个内部 shell 函数,在这种情况下它没有进程间 IO。 shell 内置函数的存在不太明显地掩盖了这种差异。就内容而言,输入和输出将是相同的。

答案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

相关内容