Arrays 在bash中可靠地传递部分命令

Arrays 在bash中可靠地传递部分命令,arrays,bash,escaping,syntax-error,eval,Arrays,Bash,Escaping,Syntax Error,Eval,我希望在bash中传递部分命令,以便: commandpart=( --flags "filename" >/dev/null ) command "${commandpart[@]}" 将评估: command --flags "filename" >/dev/null 这以前对我来说非常有效,不幸的是,将放在bash数组中会导致语法错误 意外标记“>”附近出现语法错误 `commandpart=(-flags“filename”>/dev/null)' 我尝试过的其他方法是将

我希望在bash中传递部分命令,以便:

commandpart=( --flags "filename" >/dev/null )
command "${commandpart[@]}"
将评估:

command --flags "filename" >/dev/null
这以前对我来说非常有效,不幸的是,将
放在bash数组中会导致语法错误

意外标记“>”附近出现语法错误
`commandpart=(-flags“filename”>/dev/null)'

我尝试过的其他方法是将其全部粘贴到字符串中并
eval
ing它:

commandpart="--flags filename >/dev/null"
eval "command $commandpart"
但这会带来转义、空间等方面的问题(而eval并不是一个最佳实践)

最好是,如何在不转义字符(如
&
)的情况下修复第一个示例中的语法错误?我想继续使用这个数组语法,因为它似乎比eval更健壮,并且不需要转义

如果没有,是否有其他方法可以移动命令的各个部分,以满足我的需要

额外积分:如果我将参数传递给脚本以执行如下操作:

#!/bin/bash
echo "script running"
command "${@}"
我有一个新问题,将
/dev/null
添加到脚本调用会将其应用到脚本,而不是命令:

$ script >/dev/null
转义时,它将其应用于命令,但作为不具有预期效果的字符串。(例如,如果命令是firefox,它将在一个名为“>/dev/null”的页面打开firefox,并立即打开404)

您将想了解为什么这是一个问题,并且不会真正按照您希望的方式工作。

来自bash(1):

一个简单的命令是一系列可选变量赋值,后跟空格分隔的单词和重定向,并由控制运算符终止。第一个字指定要执行的命令,并作为参数0传递。其余的单词作为参数传递给被调用的命令

这意味着重定向不是命令行的一部分。它们被BASH解释为命令所运行的“环境”的一部分,与分配其之前的环境变量一致。

来自同一个bash(1):

将命令行拆分为单词后,将在命令行上执行展开

这暗示了这样一个事实:在时间参数展开(在您的例子中为“${commandpart[@]}”)发生时,单词已经从重定向中分离出来。由于这种情况不太可能发生两次,这意味着参数扩展的结果不会被解释为重定向

您可以通过创建一个函数来实现这一点,该函数将引用非重定向的数组元素,遵循bash引用规则,然后将它们作为参数传递给eval。然而,该函数必须能够像bash一样区分重定向和“单词”,而且还有很多。这也可能需要引用某些类型重定向的部分内容


我建议不要存储/传递重定向,而是在必要时应用它们来代替调用。如果您总是需要一些带有命令的重定向,请创建包装函数或脚本。

因此,我基本上必须添加一个变量或选项来手动启用重定向?类似于:
if$tonull;然后,;命令“${commandpart[@]}”>/dev/null;其他的命令“${commandpart[@]}”;fi
不知道你的任务很难说。但是,通过包装函数,我的意思是有这样的内容:“函数quiet_command(){command“$@”>/dev/null;}”,因此如果希望放弃其输出,可以编写“quiet_command arg1 arg2 arg3”而不是“command arg1 arg2 arg3”。或者,如果您希望使其通用化,例如:“function quiet(){“$@”>/dev/null;}”,并编写“quiet命令arg1 arg2 arg3”或“quiet另一个_命令arg1 arg2 arg3”。这些函数也可以制作成单独的包装器脚本。