关于bash:如何创建一个参数位于中间的别名?

How do I create an alias where the arguments go in the middle?

本问题已经有最佳答案,请猛点这里访问。

我正在尝试定义一个别名,其中参数插入到中间,而不是附加到末尾。

我尝试像这样定义它:

1
alias grep_logs="grep $1 */log/*.log"

其中$ 1是grep_logs的第一个参数,例如:

1
grep_logs foo

将执行以下命令:

1
grep foo */log/*.log

但相反,它运行命令:

1
grep foo */log/*.log foo

这导致错误:

1
grep: foo: No such file or directory

是否可以使用别名来执行此操作,还是需要定义函数?


尝试在?/ .profile中定义一个函数。

1
2
3
function greplogs(){
    grep"$1" */logs/*.log
}


只是为了回答这个问题,虽然功能解决方案更清晰:

1
2
3
4
5
6
7
8
alias sstatus='bash -xc '\''sudo service $0 status'\'''
alias sstart='bash -xc '\''sudo service $0 start'\'''
alias sstop='bash -xc '\''sudo service $0 stop'\'''


$sstatus cups
+ sudo service cups status
Status of Common Unix Printing System: cupsd is running.


扩展@ erjoalgo的答案到目前为止是唯一一个真正回答问题的答案:

alias参数

Shell别名接受参数,但仅限于结尾:

1
2
3
$ alias speak=echo
$ speak hello world
hello world

通过alias将参数置于命令的中间确实是可能的,但它变得丑陋。

不要在家里尝试这个,小子!

如果您喜欢规避限制并做其他人认为不可能的事情,那么这就是配方。如果你的头发被弄得疲惫不堪,你的脸最终会被煤烟疯狂科学家风格覆盖,请不要怪我。

解决方法是将alias仅在最后接受的参数传递给将在中间插入它们然后执行命令的包装器。

解决方案1

如果你真的反对使用函数本身,你可以使用:

1
2
3
$ alias wrap_args='f(){ echo before"$@" after;  unset -f f; }; f'
$ wrap_args x y z
before x y z after

如果只需要第一个参数,可以用$1替换$@

解释1

这会创建一个临时函数f,它会传递参数(注意在最后调用f)。 unset -f在执行别名时删除函数定义,因此之后不会挂起。

解决方案2

您还可以使用子shell:

1
$ alias wrap_args='sh -c '\''echo before"$@" after'\'' _'

解释2

别名构建如下命令:

1
sh -c 'echo before"$@" after' _

评论:

  • 占位符_是必需的,但它可以是任何东西。它被设置为sh$0,并且是必需的,以便第一个用户给定的参数不被消耗。示范:

    1
    2
    sh -c 'echo Consumed:"$0" Printing:"$@"' alcohol drunken babble
    Consumed: alcohol Printing: drunken babble
  • 单引号内的单引号是必需的。这是一个不使用双引号的例子:

    1
    2
    $ sh -c"echo Consumed: $0 Printing: $@" alcohol drunken babble
    Consumed: -bash Printing:

    这里交互式shell的$0$@的值在传递给sh之前被替换为双引号。这是证据:

    1
    2
    echo"Consumed: $0 Printing: $@"
    Consumed: -bash Printing:

    单引号确保这些变量不会被交互式shell解释,并按字面传递给sh -c

    您可以使用双引号和\$@,但最佳做法是引用您的参数(因为它们可能包含空格),并且\"\$@\"看起来更加丑陋,但可能会帮助您赢得混淆比赛,其中疲惫的头发是先决条件条目。


问题是别名不支持位置参数的概念。如果他们这样做了,我们就不需要功能了。所以,是的,使用一个函数,因为函数是为此目的而制作的。


不是你正在寻找的答案,但如果不想将模式指定为第一个参数,则使用-e参数

1
alias grep_logs="grep */log/*.log -e"

尝试使用一个函数然后别名它:

1
2
3
function func_grep_logs {
    grep $1 */log/*.log
}

然后

1
alias grep_logs="func_grep_logs"