执行存储在变量中的命令

Lea*_*han 11 linux bash shell

我有一个存储在变量中的命令。让我们假设变量$i具有值:

cat -nT index.php |grep 'someregex'
Run Code Online (Sandbox Code Playgroud)

当我尝试通过键入执行上述变量$i时失败,因为 shell 尝试将整个变量作为一个命令执行。我也尝试使用eval($i)和添加$i反引号。

如何让 shell$i像执行命令一样执行?为什么它的工作方式不一样。

$i='echo hi'; $i
Run Code Online (Sandbox Code Playgroud)

是因为我不得不在单引号中进行某种修改吗?(因为你不能嵌套它们。)目前我的解决方案是

echo $i > /foo;  . /foo
Run Code Online (Sandbox Code Playgroud)

但我不想为此创建一个文件,以后再删除它。

我的意思是“我在单引号中黑了我做了:

$i='cat index.php | grep -P '"'"'MYREGEXHERE'"'"
Run Code Online (Sandbox Code Playgroud)

Gor*_*son 18

简短回答:参见BashAQ #50:我试图将命令放入变量中,但复杂的情况总是失败!.

长答案:这是因为 bash 解析命令行的顺序。具体来说,它在扩展变量值之前查找管道和重定向之类的东西,并且不会返回并重新查找扩展值中的管道等。本质上,变量在解析过程的中途被替换,因此该值仅在执行前被中途解析。

为了解决这个问题,您需要回答@slhck 的问题:为什么命令首先存储在变量中?你试图解决的实际问题是什么?根据实际目标,有多种可能的解决方案:

  • 不要将其存储在变量中,直接执行即可。存储命令供以后使用是很棘手的,如果您真的不需要,那就不要。

  • 使用函数而不是变量。毕竟,这就是他们的目的:

    i() { cat -nT index.php |grep 'someregex'; }
    i
    
    Run Code Online (Sandbox Code Playgroud)

    这样做的主要缺点是您不能动态创建函数——您不能有条件地从函数中包含或排除代码(尽管函数本身可以具有在执行时选择的条件元素)。

  • 使用eval. 这应该被视为最后的手段,因为很容易出现意外行为。它本质上通过另一个完整的解析传递运行命令,因此所有管道等都得到了它们的全部含义——但这也意味着您认为只是数据的命令部分也将被解析并可能被执行。包含 shell 元字符(管道、分号、引号/撇号等)的文件名可能会产生奇怪的、有时甚至是危险的效果。如果你确实使用了eval,至少用双引号引用字符串,否则它的内容基本上会被解析一次半,结果甚至更奇怪。

    i="cat -nT index.php |grep 'someregex'"
    eval "$i"
    
    Run Code Online (Sandbox Code Playgroud)

编辑:另一种标准的 store-a-command-in-a-variable 方法是使用数组而不是简单的变量。这使您可以毫无困难地存储带有复杂参数(例如包含空格)的命令,但不会存储诸如管道和重定向之类的东西。因此,数组方法在这种特殊情况下没有用。


miq*_*miq 2

声明变量时,不应使用美元符号作为前缀。

尝试这个:

i='echo hi'; $i
Run Code Online (Sandbox Code Playgroud)