说我有一个 bash 脚本/home/me/test/sh
:
#!/bin/bash
# cmd # here is the output of the cmd
pwd echo 'aaa' # /home/me
val=pwd echo 'aaa' # aaa
val=pwd echo 'aaa'$val # aaa
val=pwd echo 'aaa' && echo $val # aaa <and an empty line>
我不太明白这些用空格分隔的 bash 代码是如何工作的。
顺便说一句,我提出这个问题是因为我刚刚安装了 ROS 并且setup.sh
生成了一个名为 bash 的脚本,并且我正在阅读这个脚本。有一行如下:
CATKIN_SHELL=bash /opt/ros/kinetic/_setup_util.py >> file.log
答案1
所以我认为这里让你困惑的是命令格式,其中命令中的第一个单词是变量赋值(shell 根据 . 的存在来确定=
)
在这些情况下,shell 将评估这些分配,但它会仅有的导出正在运行的命令中的这些变量。特别是,shell 本身无法访问这些变量。
这对于运行受环境变量影响的命令或脚本很有用,在这种情况下,您不需要将它们导出到 shell 中,只需将它们设置为单次执行的“一次性”即可。
让我们分解您的命令并一一解释它们:
pwd echo 'aaa' # /home/me
好的,这就是运行pwd
命令并向其传递两个参数,echo
和aaa
。但pwd
不接受参数,所以它只是忽略这两个并打印本地目录。
val=pwd echo 'aaa' # aaa
正如我所解释的,这会执行变量赋值,设置$val
为包含字符串pwd
,然后echo
使用参数执行命令aaa
。变量$val
可用仅有的到echo
命令而不是 shell 本身!该echo
命令实际上并没有对该变量执行任何操作,因此它只是继续并打印aaa
.该命令执行完毕后,$val
变量为不是在 shell 中定义。
val=pwd echo 'aaa'$val # aaa
所以,再次类似于上面的命令。这有点棘手,因为你可能期望决赛$val
会扩大。但变量却扩大了通过外壳,而不是通过命令。而且,正如所解释的,shell 并没有真正看到$val
哪个设置为pwd
,只有命令(在本例中为echo
)可以看到,因此$val
会扩展为空字符串,这与上面的完全相同。
val=pwd echo 'aaa' && echo $val # aaa <and an empty line>
还有一次,$val
在第一个命令完成后不可用echo
,因此第二个命令echo $val
将不打印任何内容(只是空行),因为$val
在整个执行过程中从未在 shell 本身中真正设置过。
如果您想$val
在 shell 中进行设置,那么您需要使该分配成为独立的,而不需要任何命令。例如,这与上面的行为不同:
$ val=pwd; echo 'aaa' && echo $val
aaa
pwd
由于val=pwd
后面跟着一个;
,那么 shell 会将其视为自己的命令,并将$val
在当前 shell 中设置,因此echo $val
将按您的预期工作。
(请注意,这里还有一个区别,因为使用 时val=pwd; ...
,变量$val
并未真正导出,因此echo
将不是在其环境中查看该变量,同时使用val=pwd echo ...
它会被导出,但在这种情况下,它在 shell 中不可用。)
考虑到您正在使用pwd
,我想知道您是否想要将该命令的输出存储在变量中......在这种情况下,您需要使用shell命令替换$(
,或者使用反引号,或者更好的是,用and包围命令)
。
最后一个例子是:
$ val=$(pwd); echo 'aaa' && echo $val
aaa
/home/me
或者:
$ val=$(pwd) && echo 'aaa' && echo $val
aaa
/home/me
(这里有一个微妙的区别,如果替换内的命令(在本例中pwd
)失败并以非零状态退出,则后者将中断执行,在这种情况下,以下命令将不会被执行。使用时,;
这不是在这种情况下,即使第一个命令失败,也会执行以下命令。)
我希望这能解释您对这些命令不理解的地方!
答案2
下面的代码可能有助于理解这个构造是如何工作的:
$ cd tmprun/
$ cat run.sh
echo $a
$ ./run.sh
$ a=bla ./run.sh
bla