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


8

在Shell编程语言中,扩展替换似乎可以在相同的上下文中互换。例如,某些文件(例如Bash参考手册Bash Hackers Wiki)使用“扩展”一词来解释“外壳参数扩展 ”。但是,其他一些文件似乎更喜欢“替代”一词。《高级Bash脚本指南》使用参数替换

在shell编程术语方面,“扩展”和“替代”之间有什么区别吗?


两者在不同的环境中,如有效variable expansioncommand substitution。你有什么疑问
devnull

没有特定的上下文,恐怕这太笼统不清楚
devnull 2014年

查看bash手册页,通常只在涉及shell内部的东西时使用“扩展”一词,而对于涉及外部过程的东西似乎更喜欢“替代”。
celtschk 2014年

如果您接受我的建议,您将停止阅读这些文档,直到您完全熟悉以下文档:pubs.opengroup.org/onlinepubs/9699919799/utilities / ...当您完成对man sh和的处理后man set。然后,当您掌握了这些内容之后,就可以创建特定于Shell的文档。
mikeserv

@devnull你是对的。尽管我为上下文设置了链接,但最好使用问题显式指定上下文。我将编辑问题,以便人们可以清楚地理解它。
MS.Kim 2014年

Answers:


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在这种情况下,它可能是一个内部shell函数,在这种情况下,它没有进程间IO。Shell内置组件的存在不太明显地掩盖了这种差异。就内容而言,输入和输出将相同。

我喜欢这种解释,但是如何将其与文件名扩展相乘,后者肯定会由于操作(匹配算法)而产生一组文件名。
De Novo)'18

当然,但是为了发挥语义,“提取标识符的值”(我称之为扩展)不是操作,因此是替代吗?特别是因为“有些替代被认为是整体扩张的一部分”。即,这些词之间的关系与左右之间的区别不相似。我认为文件名扩展非常适合我最初对扩展的定义,但是我已经澄清了有关替代的内容,以使它变得更明显,为什么不是这样。
金发姑娘

我用文件名扩展来解决这个本来很直观的解释不是因为我想专门定义术语,而是文件名扩展似乎并没有检索绑定到标识符的值。在给定的外壳中,给定glob的值将不仅取决于glob,而且相同的glob可能在不同的上下文中产生不同的输出。此外,不需要绑定值以便以后检索它。该关系不是任意的(如foo =“ what you愿”; echo“ $ foo”),而是计算和结果。
De Novo '18

我想算术扩展中的表达式和值之间的关系也不是(完全)任意的,但是对于给定的扩展,无论上下文如何,肯定只有一个值。我可能只是在这里挑剔,但是考虑到这种解释,在所有shell扩展中,文件名扩展似乎是个奇怪的人。
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无法扩展,就没有替代。

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.