2010-08-12 80 views
7

我试着用管道运行命令。如何从变量运行脚本命令?

基本

single="ls -l" 
$single 

预期

它的工作原理:

multi="ls -l | grep e" 
$multi 
ls: |: No such file or directory 
ls: grep: No such file or directory 
ls: e: No such file or directory 

...难怪

bash < $multi 

$multi: ambiguous redirect 

下一个尝试

bash $multi 
/bin/ls: /bin/ls: cannot execute binary file 

只有

echo $multi > tmp.sh 
bash tmp.sh 

工作。

有没有办法执行更复杂的命令,而无需创建脚本执行?

+0

查看[BashFAQ/050](http://mywiki.wooledge.org/BashFAQ/050)。 – 2010-08-12 17:39:43

回答

11

您正在演示shell与内核之间的区别。

“ls -l”可由系统execve()调用执行。详情请参阅man execve,但这可能对您而言太多了。

“ls -l | grep e”需要shell解释来设置管道。没有使用shell,'|'字符只是传递给execve()作为ls的参数。这就是为什么你看到“没有这样的文件或目录”错误。

解决方案:

cmd="ls -l | grep e" 
bash -c "$cmd" 
+0

谢谢,任何想法为什么“bash -c”在一行中打印输出?我想要有与在命令行手动输入相同的输出。 – stacker 2010-08-12 16:27:48

+0

@stacker我不认为这是真的。我得到了和命令行一样的结果。也许你的grep只返回一行? – bukzor 2010-08-12 16:33:38

+0

发生这种情况是因为我忘记用双引号括起变量。 – stacker 2010-08-12 16:38:33

-3
时要与管道运行命令,只要运行它

。永远不要将命令放入一个变量并尝试运行它。如果你想捕捉的输出简单地执行它

ls -l |grep

,使用$()

var=$(ls -l |grep ..)

+0

命令来自不同的服务器,应该在目标机器上运行。因此它不能被硬编码。 – stacker 2010-08-12 16:29:55

+0

见http://mywiki.wooledge.org/BashFAQ/050 – ghostdog74 2010-08-13 00:22:21

0

你需要一个heredoc正确地做到这一点。在回答POSIX compliant way to see if a function is defined in an sh script时,我详细介绍了如何将脚本读入变量,以编程方式解析它以获取信息和/或根据需要修改它,然后从另一个脚本或shell函数中执行它。这基本上是你想要做什么,以及heredoc使得有可能,因为它提供了一个文件描述符:

% multi='ls -l | grep e' 
% sh <<_EOF_ 
> ${multi} 
> _EOF_ 
< desired output > 

这将解决您的简单的例子情况。看到我的其他答案更多。

-Mike