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
Bash 子shell don'的括号;存储在变量中时不工作_Bash_Shell_Unix_Parentheses_Subshell - Fatal编程技术网

Bash 子shell don'的括号;存储在变量中时不工作

Bash 子shell don'的括号;存储在变量中时不工作,bash,shell,unix,parentheses,subshell,Bash,Shell,Unix,Parentheses,Subshell,命令: ( echo 1 ) 在命令行中输入时工作正常,但如果将其存储为变量并调用,则会出现错误: (echo: command not found 代码: 当我这样调用它时,为什么它不以同样的方式计算括号并将其放入子shell中?括号是shell语法 要将存储在变量中的语法反映回shell进行处理,必须使用eval命令 仅仅将变量的值插入命令行不会触发语法的计算。这将是一个不必要的入侵评估,这将导致各种各样的问题 例如,考虑这个: arg="(parenthesized)" somecom

命令:

( echo 1 )
在命令行中输入时工作正常,但如果将其存储为变量并调用,则会出现错误:

(echo: command not found
代码:


当我这样调用它时,为什么它不以同样的方式计算括号并将其放入子shell中?

括号是shell语法

要将存储在变量中的语法反映回shell进行处理,必须使用
eval
命令

仅仅将变量的值插入命令行不会触发语法的计算。这将是一个不必要的入侵评估,这将导致各种各样的问题

例如,考虑这个:

arg="(parenthesized)"
somecommand $arg
我们只希望调用
somecommand
,并使用字符串
(括号中)
作为参数;我们不想运行子shell。这种隐式评估会将无害数据转化为实时代码,造成安全漏洞,更不用说试图避免它的编码噩梦了

处理
$arg
的规则与位置无关;即使
$arg
是命令行中的第一个元素,扩展也会以相同的方式进行:

$arg foo
参数替换将
$arg
转换为文本
(括号内)
,然后作为命令而不是shell语法进行尝试

要执行存储在
input
中的shell脚本,请使用:

eval "$input"
您也可以这样做:

input="echo 1"       # no parentheses

/bin/sh -c "$input"  # run in subshell explicitly

当然,子shell方法将代码片段提供给执行周围脚本的同一个shell,而在这里我们选择了
/bin/sh
,它可能不同于调用shell,或者具有不同的行为,即使它是指向同一shell的符号链接。

这将在中详细讨论

无引号的扩展只经历两个shell解析阶段:字段拆分和全局扩展。因此,
(echo 1)
首先被分成几个字段:
echo
1
;每个都扩展为一个glob(没有意义,因为它们都不是glob扩展);然后它们作为命令运行:
被调用,第一个参数
echo
,第二个参数
1
,第三个参数

存储代码的正确方法是在函数中:

# best-practices approach
input() ( echo 1; )
input
…或者,如果您想让读者更清楚地知道您确实想要一个子shell,并且由于错误或习惯,没有使用括号而不是大括号:

# same, but more explicit about intent
input() { (echo 1); }
input
…如果不可能,可以使用
eval
(但要注意中给出的警告):


如果在字符串中生成命令的真正原因是参数化其内容,请改用数组:

input_args=( 1 )                    # define an array
input() ( echo "${input_args[@]}" ) # use that array in a function (if needed)

# add things according to conditional logic as appropriate
if (( 2 > 1 )); then
  input_args+=( "possible argument here" )
fi

# call the function, or just use the array directly, such as: (echo "$(input_args[@]}" )
input

看见无引号的扩展只经过两个解析阶段(字段拆分和全局扩展);这是正确的,理由很充分(否则在bash中编写安全代码会困难得多)。链接的常见问题解答提供了大量详细信息,其中包括讨论了您可能希望将代码存储在变量中的情况下的最佳做法。您不能将此类命令放置在变量中。事实上,将命令放入变量很容易失败。变量保存数据,而不是命令!如果您想将命令存储在某处以备将来使用,请使用function.BTW,您的代码和错误不会对齐。您将获得
(:command not found
如果您使用的是此处给出的确切代码。请务必按照要求在问题中实际复制/粘贴代码,以避免将来出现此类情况,因为这些差异可能会产生实际影响。由于
command
是一个内置命令,因此将其用作其他随机命令的替代命令有点混淆g、 @charlesduff这是一个很好的观点,先生;它必须被修正。
# avoid this approach if at all possible
input="( echo 1 )"
eval "$input"
input_args=( 1 )                    # define an array
input() ( echo "${input_args[@]}" ) # use that array in a function (if needed)

# add things according to conditional logic as appropriate
if (( 2 > 1 )); then
  input_args+=( "possible argument here" )
fi

# call the function, or just use the array directly, such as: (echo "$(input_args[@]}" )
input