Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux Bash变量默认值不为';如果后面跟着管道(bash bug?)_Linux_Bash - Fatal编程技术网

Linux Bash变量默认值不为';如果后面跟着管道(bash bug?)

Linux Bash变量默认值不为';如果后面跟着管道(bash bug?),linux,bash,Linux,Bash,我刚刚在bash中发现了一个我不理解的奇怪行为。表情 ${variable:=default} 将变量设置为默认值(如果尚未设置)。考虑下面的例子: #!/bin/bash file ${foo:=$1} echo "foo >$foo<" file ${bar:=$1} | cat echo "bar >$bar<" #/bin/bash 文件${foo:=$1} echo“foo>$foo$bar在第二种情况下,文件是一个管道成员,在其自己的外壳中作为每个管道成员

我刚刚在
bash
中发现了一个我不理解的奇怪行为。表情

${variable:=default}
变量
设置为
默认值(如果尚未设置)。考虑下面的例子:

#!/bin/bash
file ${foo:=$1}
echo "foo >$foo<"
file ${bar:=$1} | cat
echo "bar >$bar<"
#/bin/bash
文件${foo:=$1}

echo“foo>$foo$bar在第二种情况下,
文件
是一个管道成员,在其自己的外壳中作为每个管道成员运行。当
文件
及其子外壳结束时,
$b
及其来自
$1
的新值不再存在

解决方法:

#!/bin/bash
file ${foo:=$1}
echo "foo >$foo<"

: "${bar:=$1}"     # Parameter Expansion before subshell

file $bar | cat
echo "bar >$bar<"
!/bin/bash
文件${foo:=$1}

echo“foo>$foo$bar这不是一个bug。参数扩展发生在对命令进行求值而不是分析时,但在新进程启动之前,作为管道一部分的命令不会求值。改变这一点,除了可能破坏一些现有代码外,还需要在进行评估之前进行额外的扩展

假设的
bash
会话:

> foo=5
> bar='$foo'
> echo "$bar"
$foo
# $bar expands to '$foo' before the subshell is created, but then `$foo` expands to 5
# during the "normal" round of parameter expansion.
> echo "$bar" | cat
5
为了避免这种情况,
bash
需要某种方法来标记新的第一轮预评估参数扩展所产生的文本片段,这样它们就不会经历第二轮预评估 第二轮评估。这种记账方式会很快导致无法维护的代码,因为会发现有更多的角落案例需要处理。更简单的方法是接受参数扩展将被推迟到子shell启动之后


另一种选择是允许每个组件在当前shell中运行,这是POSIX标准允许的,但也不是必需的<代码>bash
很久以前就做出选择,在子shell中执行每个组件,而反过来会破坏太多依赖于当前行为的现有代码。(
bash
4.2确实引入了
lastpipe
选项,允许管道的最后一个组件在当前shell中执行(如果显式启用)。

很可能是一个bug,您应该报告它。@ammoQ,没有类似的;记录的行为,甚至是常见问题的一部分。这是一个
bash
功能,而不是
bash
错误……这是否意味着参数扩展是在子shell中执行的,而不是在创建子shell之前执行的?@starfry:chepner在他的回答中正确地解释了这一点。在我的bash版本4.3.30中,
echo“$bar”| cat
导致打印
$foo
,而不是
5
。是;我展示的示例是假设的,不代表bash的任何真实版本,以演示如果在当前shell中扩展参数,bash将需要做额外的工作来避免这种双重扩展。
> foo=5
> bar='$foo'
> echo "$bar"
$foo
# $bar expands to '$foo' before the subshell is created, but then `$foo` expands to 5
# during the "normal" round of parameter expansion.
> echo "$bar" | cat
5