为啥在同一行上分配变量后shell内置冒号命令“:”会导致分配空字符串值?

Posted

技术标签:

【中文标题】为啥在同一行上分配变量后shell内置冒号命令“:”会导致分配空字符串值?【英文标题】:Why does shell builtin colon command ":" after variable assignment on same line cause empty string value to be assigned?为什么在同一行上分配变量后shell内置冒号命令“:”会导致分配空字符串值? 【发布时间】:2019-12-13 22:04:34 【问题描述】:

如果我在赋值后添加 colon (:) 内置 shell 命令,变量将被分配给空字符串 ("")。为什么它会这样?我预计它不会有任何效果。

    set -vx
    MyVar1='my var 1'  : colon comment here  # *** !!! This gets assigned to empty string!!!
    MyVar2='my var 2'  # hash comment here; this is fine

    echo "MyVar1 = [$MyVar1]"  # EXPECTED: 'my var 1'; ACTUAL: '' (empty string).  Why?
    echo "MyVar2 = [$MyVar2]"  # As expected.

:(冒号) :[参数] 除了扩展参数和执行重定向之外什么都不做。返回状态为零。https://www.gnu.org/software/bash/manual/html_node/Bourne-Shell-Builtins.html

【问题讨论】:

它实际上不是空的,它没有设置(尝试[[ -v $MyVar1 ]] || echo 'not set'作为测试)。 【参考方案1】:

: 是一个成功返回的内置命令(true 的简写版本)。

当您在命令的同一行进行变量赋值时,赋值仅在命令执行期间有效(这通常用于运行设置了临时环境变量的命令)。

所以当你运行时:

MyVar1='my var 1'  : colon comment here

你是:

运行命令: 传递参数coloncommenthere(这些被命令删除) 临时变量赋值MyVar1='my var 1'(这对命令没有影响)

the spec 中描述了此行为:

“简单命令”是一系列可选的变量赋值和重定向,以任意顺序,可选地后跟单词和重定向,由控制运算符终止。

...

如果没有命令名结果,变量赋值将影响当前执行环境。否则,变量赋值要为命令的执行环境导出,不影响当前执行环境(特殊内置除外)。

正如 cmets 中指出的(谢谢!): is one of the special built-ins,这意味着在符合标准的 shell 中,分配应该影响当前的执行环境。默认情况下,Bash 在这个意义上不符合规范,尽管您可以通过将其调用为 sh(在它是默认 shell 的系统上)或使用 bash --posix 来做到这一点:

$ bash -c 'foo=bar :; echo $foo'

$ sh -c 'foo=bar :; echo $foo'
bar
$ bash --posix -c 'foo=bar :; echo $foo'
bar

【讨论】:

所以你是说任何之前冒号(:)命令基本上被忽略? 命令前的任何变量赋值只会影响命令的执行环境(在你的情况下,:),而不是当前的执行环境(shell)。 注意这种行为是非标准的。根据 POSIX 规范,: 是一个 special 内置的,并且在一个 special 之前的变量赋值应该在命令完成后保持有效。如果您将bash 调用为sh 或使用--posix 选项,则会观察到OP 的预期行为。 @RobBednark 需要临时分配的一个常见示例是使用read 命令。 IFS=, read a b c 将读取一行输入,以逗号分隔,并将前三个字段分配给 ab, and c. The global value of IFS` 不受影响。 (见pubs.opengroup.org/onlinepubs/9699919799/utilities/…)

以上是关于为啥在同一行上分配变量后shell内置冒号命令“:”会导致分配空字符串值?的主要内容,如果未能解决你的问题,请参考以下文章

idea中foreach为啥分两行

awk基础

Cin>>在同一行上多次[重复]

Linux shell的输入输出

shell脚本编程

5月9日下午学习日志