执行存储在变量中的命令


11

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

cat -nT index.php |grep 'someregex'

当我尝试通过键入来执行上述变量时,$i它失败了,因为外壳程序尝试将整个变量作为一个命令执行。我使用也尝试eval($i)并把$i在反引号。

如何使Shell $i像命令一样执行?而且为什么它不能与之相同。

$i='echo hi'; $i

是因为我不得不在单引号中弄乱吗?(因为您不能嵌套它们。)目前,我的解决方案是

echo $i > /foo;  . /foo

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

我的意思是“我砍了单引号是:

$i='cat index.php | grep -P '"'"'MYREGEXHERE'"'"

4
问题是,为什么命令首先存储在变量中?您最好在运行命令时将其汇编,将选项参数存储在变量或数组中。您可以显示整个脚本吗?
slhck

Answers:


18

简短的答案:请参阅BashAQ#50:我正在尝试将命令放入变量中,但是复杂的情况总是会失败!

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

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

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

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

    i() { cat -nT index.php |grep 'someregex'; }
    i

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

  • 使用eval。这应该被认为是不得已的方法,因为很容易发生意外行为。它实质上是通过另一个完整的解析过程来运行命令,因此所有管道等都具有它们的完整含义-但这也意味着您认为只是数据的命令部分也将被解析并可能执行。包含外壳元字符(管道,分号,引号/撇号等)的文件名可能会产生怪异的效果,有时还会产生危险。如果您确实使用eval,请至少对字符串加上双引号,否则它的内容将被解析一半半,甚至得到更奇怪的结果。

    i="cat -nT index.php |grep 'someregex'"
    eval "$i"

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


+1为eval方法。这阻止了我问同样的问题:)。我有类似的东西sudo rsync -aAHXi -n --delete-excluded --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/lost+found","/mnt/DATA/*","/var/log/*","/var/swap","/var/cache/apt/archives/*.deb"} -e ssh root@piac_wireless:/ /home/mrx/Docs/RPi/backup/piac/piac_usb-root不能正确执行排除。
dentex

我强烈建议不要使用@dentex eval-出错的方法太多。数组将是一种更好的方法。有关示例,请参见此处此处此处
Gordon Davisson

谢谢你的建议。我将尝试使用数组实现解决方案,以便将排除列表传递给rsync。
dentex

4

这应该工作:

a="cat -nT index.php |grep 'someregex'"
eval "$a"

当心eval引入了潜在的漏洞和意外行为情况,因此,如果有必要,必须格外小心。


如果您确实使用eval,那么您确实需要使用双引号(eval "$i")来避免额外的怪异效果。例如,尝试使用a="cat -nT index.php |grep ' .* '"(即正则表达式应将两个空格匹配,并且空格之间可以有任意字符序列),然后看看实际发生了什么。为了获得额外的信誉,请说明原因
Gordon Davisson

@GordonDavisson添加了双引号。
jlliagre

2

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

尝试这个:

i='echo hi'; $i

1
没错,但这并不是对OP的回答。
slhck

它对我来说
真的
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.