仅用空格而不是 ; 链接 bash 或 dash 命令分号 ;或&& 或&&

问题描述 投票:0回答:1

普通的命令链方法可以正常工作,例如:

$ (SCRATCH='heya'; echo $SCRATCH)
heya

或者使用逻辑运算符 && 产生可预测的结果:

$ (SCRATCH='heya' && echo $SCRATCH)
heya

但是如果我们使用空格来链接命令,那么事情就会变得奇怪:

$ (SCRATCH='heya' echo $SCRATCH)
<<just a blank line prints here>>

尽管有上述情况,变量实际上已设置,我可以用这一行来证明:

$ (DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u $USER)/bus" grdctl status)
RDP:
        Status: enabled
        TLS certificate: /home/guest/.local/share/gnome-remote-desktop/rdp-tls.crt
        TLS key: /home/guest/.local/share/gnome-remote-desktop/rdp-tls.key
        View-only: no
        Username: (hidden)
        Password: (hidden)

上面没有分号分隔两个命令,奇怪的是它实际上以某种方式读取变量并起作用。

更奇怪的是,我可以通过插入正常的必需条件来打破它 分号 ;它确实应该在那里,像这样:

$ (DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u $USER)/bus"; grdctl status)
Failed to lookup legacy VNC password schema: Cannot autolaunch D-Bus without X11 $DISPLAY
Failed to lookup RDP credentials: Cannot autolaunch D-Bus without X11 $DISPLAY

接下来,保留有问题的分号...... 我可以通过导出变量让它恢复生机, 这让我认为 grdctl 命令将自身放入子 shell 中:

$ (export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u $USER)/bus"; grdctl status)
RDP:
        Status: enabled
        TLS certificate: /home/guest/.local/share/gnome-remote-desktop/rdp-tls.crt
        TLS key: /home/guest/.local/share/gnome-remote-desktop/rdp-tls.key
        View-only: no
        Username: (hidden)
        Password: (hidden)

但是,如果我们直接运行以下空格分隔的命令,那么变量就会消失得无影无踪,甚至没有任何错误!

$ SCRATCH='heya' echo $SCRATCH
<<just a blank line prints here>>

如果我导出变量,那么情况会变得更糟,甚至不会打印空行!

$ export SCRATCH='heya' echo $SCRATCH
<<just a blank line prints here>>

上面的行为似乎极其不一致,因为 echo 命令的行为方式是一种,而 grdctl 的行为方式是另一种。

我不断地用谷歌搜索并咨询人工智能,但没有人能解释带空格的命令链,这绝对是“一件事”,因为它经常起作用。

互联网上有数以万计的关于如何做的解释;或 && 或 ||可用于链接命令,但不能用于查看空格字符。

有人有什么想法吗?

bash variables command chaining subshell
1个回答
0
投票

事实上,bash 允许在执行命令之前“动态”定义导出的临时环境变量。

SOME_VAR_TO_BE_EXPORTED="value only for the command" some_command

示例:

echo 'printf "MY_ENV_VAR=%s" $MY_ENV_VAR\n' > myscript.sh
chmod a+x ./myscript.sh

现在让我们使用 前缀 env var 定义来执行它

# just to be sure
unset MY_ENV_VAR
MY_ENV_VAR=value ./myscript.sh

将输出:

MY_ENV_VAR=value

但是

$MY_ENV_VAR
范围仅在调用期间存在(假设之前没有设置)

echo $MY_ENV_VAR

应该是空的

这里有一些解释:

https://www.baeldung.com/linux/set-env-variables-bash-command

官方文档在这里

https://www.gnu.org/software/bash/manual/html_node/Environment.html

段落:

任何简单命令或函数的环境都可以通过在其前面添加参数分配来临时增强,如 Shell 参数中所述。这些赋值语句仅影响该命令所看到的环境。

所以,是的,这是一个令人困惑的语法。缺少的分号是为了这个特定的语法而故意的,它只适用于 envvar 分配。

分号会产生不同的行为:2 条指令。因此定义变量,不需要也导出它,然后执行命令(最终在执行第二条指令之前扩展变量)

希望有帮助,继续阅读文档,😉并且可以看看shellcheck,你可能会学到更多技巧。

想成为命令行战士吗?也许这个网站仍然有贡献

https://www.commandlinefu.com/commands/browse/sort-by-votes

厌倦了令人讨厌的语法?为什么不学Python呢?还是红宝石?

玩得开心!😜

© www.soinside.com 2019 - 2024. All rights reserved.