别名可以使用位置参数吗?

别名可以使用位置参数吗?

我的 中有以下行.bashrc

#!/usr/bin/env bash
alias see='nano --view $1'

但现在shellcheck正在产生一个高优先级警告:

别名不能使用位置参数,而应使用函数。

合理,除了一件事:它工作得很好!这是怎么回事?

答案1

不,还有它作品因为通常$1是空的[1]并且不被引用。由此产生的命令see foo将是see foo.

但是,如果您引用它,如下所示:

alias see='nano --view "$1"'

它会变成see <empty> foo,你会打开一个新缓冲区除了foonano.


[1] $1扩展为无论 shell 的第一个位置参数的值是多少- 在交互式 shell 中通常什么都没有(因为交互式 shell 通常不使用位置参数来调用),但是没有什么可以阻止它被设置为任意值(例如使用set外壳内置/ help set) -set -- foo bar; see baz例如foo然后将打开baz(从评论中自由复制@steeldriver因为这是一个重要的注释。)

所以不要相信它总是空的。


您还可以尝试:

$ alias e='echo @$1@'
$ e foo  <-- would become: echo @$1@ foo
@@ foo
|  |
|  +--- foo is next string
+------ $1 is empty

在引擎盖下可以这么说你会看到就像是:

execve("/bin/nano", ["nano", "--view", "foo"], 0xabc...)

对于引用的版本:

execve("/bin/nano", ["nano", "--view", "", "foo"], 0xabc...)

在主要功能中nano

int main(int argc, char *argv[])

argc,(参数计数)将分别为 3 和 4,并且argv,(参数向量/数组)将是方括号中的字符串。


您可以使用:

alias see='nano --view'

然后通过发出:

$ see foo

foo将是$1, (不是真的$1,而是比较而言),并且该命令将扩展为:

nano --view foo

如果您需要将 nano 限制为只开放$1,(第一个参数),您需要一个函数,因为:

see foo bar

将扩展到nano --view foo bar

然后你可以使用类似的东西:

see() {
    nano --view "$1"
}

那么你会丢弃上面的任何参数$1以及何时execve被调用它总是:

execve("/bin/nano", ["nano", "--view", "filename"], 0xabc...)

filename位于哪里。$1bashNano看不到$1,只有价值。 Bash 负责处理这个问题。


当使用 shell 函数时,参数被定义为位置参数,$1, $2, $3, …,并且功能可以访问这些。别名不被视为函数,因此它无法访问这些参数/它们不存在。

尝试:

alias p1='echo "$# $1 END"'
p2() { echo "$# $1 END"; }

结果:

$ p1 a b c
0  END a b c

$ p2 a b c
3 a END


一般来说,Bash 手册指出:

对于几乎所有用途,shell 函数都优于别名。

没有像 csh 中那样在替换文本中使用参数的机制。如果需要参数,则应使用 shell 函数(请参阅外壳函数)。


为了shellcheck写下来,请参阅 SC2142 的 wiki

答案2

别名不要接受参数,它们只是按原样复制。他们似乎(有时)工作(某种程度上)。但事实并非如此。

使用外壳函数。

相关内容