哪些字符可以在Bash别名中使用?

18

我最近添加了

alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'

我希望你能添加一些到我的bash_aliases文件中。在尝试时,我注意到虽然可以使用别名来代替..,但却不能代替.。那么在bash别名中允许使用哪些其他标点符号?


4
你使用的是哪个版本的bash?我可以成功地为.设置别名。然而,在POSIX规范中,.已经被定义为一个命令名,所以你可能不应该用别名来覆盖它。 - chepner
4个回答

9
Bash别名绝对不能包含以下字符:空格 、制表符\t、换行符\n/\$`=|&;()<>'"。根据Bash参考手册says

别名名称中不能出现字符/$`=和任何上面列出的shell元字符或引用字符。

“Shell元字符”定义为:

一个未被引用时分隔单词的字符。元字符是一个空格,制表符,换行符或以下字符之一:|,&,;,(,),<或>。 "引用字符" 没有明确列出,但它们是反斜杠(\)和单引号(')和双引号(")。

Bash检查别名名称legal_alias_name(),该函数在这里实现:1, 2, 3。查看我系统上mksyntax.c(一个生成另一个C程序的C程序)的输出,shellbreak()将对这10个字符返回true:\t\n &();<>|shellxquote()对这4个字符返回true:"'\`,而shellexp()$返回true,最后legal_alias_name()还检查了/

然而,还有其他限制,包括1)Bash如何对您编写的alias表达式进行标记化以定义别名,以及2)它如何对以您的别名开头的命令进行标记化。对于第一个限制,=不能出现在别名名称中,可能是因为alias foo=bar=baz将被解析为foo=bar=baz,而不是foo=bar=baz。对于第二个限制,在我的实验中,您可以使用!history expansion字符)定义别名,但如果尝试使用它,除非!位于命令末尾,否则会出现command not found错误。最安全的做法是只使用数字、字母和下划线。

1
为了完整起见:我在许多“危险”命令中使用 !(例如强制推送 gpf! 或交互式变基 gri!),但只作为最后一个字符。不确定它们是否适用于别的别名位置。来到这个帖子是想看看我还能怎么使用 ! :) - Xunnamius
1
@Xunnamius alias "abc!"=echo 可以运行,但 alias "a!bc"=echoalias "a\!bc"=echoalias "!abc"=echo 无法运行。 - user3064538

8

使用函数一直是更安全的选择:

function .. { cd '..'; }
function ... { cd '../..'; }
function .... { cd '../../..'; }

或者对于保守偏好:
..() { cd '..'; }
...() { cd '../..'; }
....() { cd '../../..'; }

这种方法有哪些安全性优点呢?别名会影响一流语法(if、case等),其命令使用引号指定。这就像不必要地使用eval。另一方面,使用函数则很简单,并且您可以准确了解参数是如何展开的。简而言之,别名是一种hack。这就像在C中使用#define语句一样,当您可以简单地定义一个函数时。这是初学者想要组合的东西。
如果任何人想要为命令定义默认参数,则可以使用命令使函数调用外部命令以避免递归。这才是正确的方法。例如:function grep { command grep --color=auto“$ @”; }

9
用这种方式做有什么更安全的地方? - elju

4
根据这个网站的说明,环境变量名只能包含以下字符:大写字母、数字和'_'(下划线),这些字符是可移植字符集中定义的,并且不能以数字开头。其他字符可能会被某些实现允许;应用程序应该能够容忍这样的名称存在。
但是变量名并不完全等同于别名。
实际上,在实践中,debian(apt-get)的一个事实标准是应该将-(破折号)添加到列表中。此外,_~@#%^.,都可以使用,而><'\"|=()`/?[]+!则不能使用。另外还要担心$PATH和像:这样的特殊字符。如果正确转义或引用,空格和换行符似乎也可以工作,如"a b"

1
我尝试在我的别名中使用 / 符号,但是它没有起作用。 - Andrew
3
GNU bash手册中指出,“字符/$`=以及任何上述列出的shell元字符或引用字符都不能出现在别名名称中。”因此,这个回答(声称/$是可以的)是错误的。 - user3064538

1

2
“..”只是一个(特殊的)目录名称,因此在语法上与“foobar”之类的东西没有任何区别。 - chepner
我知道,通常这并不重要,但如果你将它放在bashrc中,当某些系统试图执行它时,会导致cd到它,这会很奇怪,这就是为什么像konsolebox所说的那样,函数更安全。 - DTSCode
4
无论你将..定义为别名或函数,所描述的问题是一样的,但如果..作为一个参数被使用,那么它们都不会被调用。由于.bashrc仅在交互式shell下被调用,所以不必担心会改变任何shell脚本的行为,尤其是系统脚本(只要你不搞乱/etc/bashrc,因为这些脚本将以root身份而非用户身份运行)。 - chepner
1
啊,好的,我明白你的意思了。 - DTSCode

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接