在变量中执行命令

Kaj*_*Kaj 6 grep bash

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

cmd="grep -i \"word1\" filename | grep -i \"word2\""
eval $cmd
Run Code Online (Sandbox Code Playgroud)

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

grep: |: No such file or directory
grep: grep: No such file or directory
Run Code Online (Sandbox Code Playgroud)

如何在不出现此错误的情况下执行示例中的命令?

mik*_*erv 5

你需要引用"$cmd"- 也许避免"双引号。无论如何,要运行它,您确实需要eval它 - 这是由于|pipe. shell 变量不会超出单个简单命令的限制 - 而您正在尝试运行复合命令。

所以:

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

eval "$cmd"
Run Code Online (Sandbox Code Playgroud)

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

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

grep: |: No such file or directory
grep: grep: No such file or directory
Run Code Online (Sandbox Code Playgroud)

所以如果我这样做:

echo | echo
Run Code Online (Sandbox Code Playgroud)

第一echo打印一个\newline到所述第二echostdin。如果我做:

set \| echo
echo "$@"
Run Code Online (Sandbox Code Playgroud)

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

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

所以如果你这样做:

grep -i "word" filename \| grep -i "word2"
Run Code Online (Sandbox Code Playgroud)

...您可能会得到相同的结果,因为|there 没有分隔命令,而是grep在其infiles位置中的一个参数。

以下是$cmd使用 default拆分时获得的字段数量$IFS

printf '<%s> ' $cmd
<grep> <-i> <"word1"> <filename> <|> <grep> <-i> <"word2">
Run Code Online (Sandbox Code Playgroud)

这是文件名生成可能会做的事情:

touch 'echo 1simple &&' 'echo 2simple'
eval echo*
Run Code Online (Sandbox Code Playgroud)