我正在尝试执行一个存储在变量中的命令:
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)
如何在不出现此错误的情况下执行示例中的命令?
你需要引用"$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到所述第二echo的stdin。如果我做:
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)