在函数内执行传递的别名?

时间:2013-01-25 17:55:15

标签: bash

背景

我正在尝试创建一个在设定的时间间隔内运行命令的函数,因为我无法访问“监视”程序。简化为最基本的,我正在尝试编写的函数是runit() { $1; }

什么有效:

当我传递非别名的东西时,这很好用。例如,runit "ls -l"工作正常。我从ls -l命令获得完整输出。

什么行不通:

当我传递别名时问题就开始了。例如,设置alias ll="ls -l"然后调用runit "ll"将导致-bash: ll: command not found

我尝试过的事情:

当我对别名runit() { ll; }进行硬编码时,它运行正常,并给出了我的期望。


我觉得我可能会忽略某些东西,但我无法将手指放在它上面 为什么硬编码别名工作正常,但将其传递给函数失败?
有没有办法完成我想要做的事情?

3 个答案:

答案 0 :(得分:7)

bash手册页讨论别名(强调我的):

  

在读取命令时扩展别名,而不是在执行时扩展别名。   因此,一个          与另一个命令出现在同一行的别名定义在读取下一行输入之前不会生效。该   命令          在该行上的别名定义之后不受新别名的影响。当函数出现时,这种行为也是一个问题   执行。 在读取函数定义时扩展别名,而不是在函数执行时扩展,因为函数   定义是          本身就是一个复合命令因此,在执行该函数之后,函数中定义的别名才可用。   至          安全,始终将别名定义放在单独的行上,并且不要在复合命令中使用别名。

您可以使用type命令在函数中观察此效果:

$ run_it () { ll; }
$ type run_it

您应该看到该函数的正文包含对ls -l的调用,而不是ll

关于别名的部分的最后一句:

  

对于几乎所有目的,别名都被shell函数取代。

我对该行的解释是:如果您认为要使用别名,请先尝试编写函数。除非功能明显无法满足您的需求,否则请勿使用别名。

答案 1 :(得分:4)

解决此问题的一种方法是定义shell函数而不是别名。

ll () {
  ls -l "$@"
}

别名在命令输入时作为宏扩展,而在执行命令时匹配shell函数。这是shell的宏处理器语言如何有利于交互式优雅而不是实际编程复杂化的完美示例。

答案 2 :(得分:3)

您可以像这样使用eval

$ runit() { eval $1; }
$ alias ll="ls -l"
$ runit "ll"

eval会在执行前展开$1中的所有别名。