执行变量内的命令

执行变量内的命令

我正在尝试执行存储在变量中的命令:

cmd="grep -i \"word1\" filename | grep -i \"word2\""
eval $cmd

但是当我执行脚本时,我收到错误:

grep: |: No such file or directory
grep: grep: No such file or directory

如何执行像我的示例中那样的命令而不出现此错误?

答案1

您需要引用"$cmd"- 并且可能避免使用"双引号。不管怎样,要运行它,你确实需要eval它 - 这是由于|pipe. shell 变量不会扩展到超出单个简单命令的限制 - 并且您正在尝试运行复合命令。

所以:

cmd='grep -i "word1" filename | grep -i "word2"'

eval "$cmd"

可能当您在没有引号的情况下进行扩展时,$cmd您会遇到文件名生成和/或$IFS问题。只要确保它被可靠地引用就可以了。还要验证其中的内容"word[12]"不包含双引号或反斜杠或其他任何内容 - 否则您需要在那里重新评估您的引用样式。

现在仔细看看你的错误,我可以准确地告诉你它是什么:

grep: |: No such file or directory
grep: grep: No such file or directory

所以如果我这样做:

echo | echo

第一个将 ewlineecho打印\n到第二echostdin。如果我做:

set \| echo
echo "$@"

第一个echo打印它的每个参数,分别是|管道和echo

不同之处在于,|第一种情况下的管道被 shell 的解析器解释为标记,并被如此解释。在第二种情况下,shell 在扫描|管道令牌的同时,也在扫描$扩展令牌 - 因此|管道尚未被发现,因为"$@"尚未被其值替换。

所以如果你这样做:

grep -i "word" filename \| grep -i "word2"

...您可能会得到相同的结果,因为 There|没有分隔命令,而是grep它的参数内文件位置。

$cmd以下是使用默认值进行拆分时获得的字段数量$IFS

printf '<%s> ' $cmd
<grep> <-i> <"word1"> <filename> <|> <grep> <-i> <"word2">

文件名生成可能会执行以下操作:

touch 'echo 1simple &&' 'echo 2simple'
eval echo*

答案2

对于我来说使用方法错误多变的保存并执行任何命令。还有更好的选择——功能:

my_cmd() {grep -i "word1" filename | grep -i "word2"}

就这些。

或者您可以使用不同的参数,例如:

my_cmd() {grep -i "$1" "$3" | grep -i "$2"}

然后通过调用它

my_cmd word1 word2 filename

答案3

对于您发布的示例,您不需要评估。只需像这样执行变量:

cmd="grep -i \"word1\" filename | grep -i \"word2\""; # added missing " at the end    
$cmd

注意你的报价。也许这样的事情不太容易出错:

cmd='grep -i "word1" filename | grep -i "word2"';

相关内容