在Shell编程语言中,扩展和替换似乎可以在相同的上下文中互换。例如,某些文件(例如Bash参考手册,Bash Hackers Wiki)使用“扩展”一词来解释“外壳参数扩展 ”。但是,其他一些文件似乎更喜欢“替代”一词。《高级Bash脚本指南》使用参数替换。
在shell编程术语方面,“扩展”和“替代”之间有什么区别吗?
man sh
和的处理后man set
。然后,当您掌握了这些内容之后,就可以创建特定于Shell的文档。
在Shell编程语言中,扩展和替换似乎可以在相同的上下文中互换。例如,某些文件(例如Bash参考手册,Bash Hackers Wiki)使用“扩展”一词来解释“外壳参数扩展 ”。但是,其他一些文件似乎更喜欢“替代”一词。《高级Bash脚本指南》使用参数替换。
在shell编程术语方面,“扩展”和“替代”之间有什么区别吗?
man sh
和的处理后man set
。然后,当您掌握了这些内容之后,就可以创建特定于Shell的文档。
Answers:
在这种情况下,替代几乎是扩展的同义词,因为它们的含义重叠。这两个都不是另一个完整的子类别,尽管您在GNU手册部分中引用了一些替换,这些替换被视为整体扩展的一部分。
的膨胀被提取标识符的值。例如,如果this=that
,当我们扩展时,this
我们得到that
。不涉及替换的扩展是预先确定的,因为所使用的值已经存在并且必须简单地进行检索,尽管这包括合并检索的/显式的值(例如使用“算术扩展”)。
甲替代产生一个值作为一个明确的输入/输出操作的结果。例如,如果this=$(foo bar)
,this
是执行的结果foo bar
和捕获其输出。1尽管替换产生的值可能是完全可预测的,但它与正常扩展中检索到的值不同,因为在替换发生之前它实际上并不存在,而是产生出来的。
替换有两种风格,即命令和过程,这两种是对称的:
# Command substitution
foo=$(ls)
# Process substitution
wc <(ls)
第一个中的“命令”为ls
,第二个中的“进程”为。我们可以说被替换的实际上是管道的末端。进程替换与重定向重叠。但是,从技术上讲这可能有点过于严格了,这使我们成为脚注...
foo bar
在这种情况下,它可能是一个内部shell函数,在这种情况下,它没有进程间IO。Shell内置组件的存在不太明显地掩盖了这种差异。就内容而言,输入和输出将相同。 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
无法扩展,就没有替代。
goldilocks很好地说明了替代物的空灵存在。我猜有点像薛定inger的猫。它使我想起了什么。您可能不熟悉这种形式的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
variable expansion
,command substitution
。你有什么疑问