我一直在玩参数扩展。以下是我的代码。
a="one"
sh -c 'echo $a'
b="two"
sh -c "echo $b"
c="three" sh -c 'echo $c'
echo $c
这是我执行此脚本时的输出:
$sh test.sh
two
three
$
对于 $a,如果单引号会抑制替换。它不应该只打印 echo $a 吗?它正在打印一个新行,这是否意味着 $a 的值为空?对于 $c,“echo $c”不起作用,不会打印新行,但下一行中的 echo $c 按预期工作。我有点困惑这是如何工作的。
答案1
sh -c 'echo $a'
就像打开一个新的外壳并echo $a
在其中输入一样。由于子 shell 中没有变量a
(您没有export
在父 shell 中设置变量),因此它将打印一个空行。
和
b="two"
sh -c "echo $b"
,该"echo $b"
字符串由当前 shell 展开,并将展开后的值作为参数字符串传递给子 shell。就好像您打开了一个新 shell 并输入了echo two
。
var=val command
暂时设置 和export
s var=val
,只是为了调用command
.
c="three" sh -c 'echo $c'
几乎(子壳并不真正存在)就像
( export c="three"; sh -c 'echo $c' )
父 shell 中的 c 变量不受影响。
答案2
如果您想查看子流程中的变量,则必须查看export
它们。像这样:
$ export a=7
$ sh -c 'echo $a'
7
在您的情况下,子进程( fora
和b
)看不到来自父 shell 的变量。
当您使用单引号创建字符串时,所有替换都不起作用。您不能替换变量或类似的东西\n
。它将恰好是$a
或\n
。因此,第一种情况下的字符串正是“echo $a”。sh -c 'echo $a'
将创造新的进程,并且该进程不会有父进程$a
,它将有自己的 uninitialized $a
,即空字符串。它只会执行'echo $a'
在第二种情况下,您使用双引号。替换有效,字符串变成"echo two"
前执行子进程。所以,这只是执行sh -c 'echo two'
。
在第三种情况下,$c
成为导出变量。这是一种特殊的语法,意味着“仅为此命令导出变量”。因此,您准确执行sh -c 'echo $c'
,但新的 shell 将包含$c
作为环境变量。就像$PATH
或$HOME
当你启动 shell 时一样。