设置别名
我想在一个脚本来创建一个别名,像这样:设置别名
#!/bin/bash
shopt -s expand_aliases
#Currently just using 'git' to try and get it working
#It'll be replaced with the following line when it works
#compgen -c | while read x;
echo 'git' | while read x;
do
a=`echo $x | tr '[:lower:]' '[:upper:]'`;
echo $a;
echo $x;
if [ "$a" != '' ]
then
echo 'got here';
alias $a=$x;
alias;
GIT;
fi
done
而一个简单的测试脚本作品(testme
添加到别名在我当前的shell):
#!/bin/bash
shopt -s expand_aliases
alias testme="echo It Worked"
alias
testme
输出:
GIT
git
got here
alias GIT='git'
alias grep='grep --colour=auto'
alias ls='ls --color=auto'
GIT: command not found
GIT
在别名显示了,BU t不能执行。我试过用. ./script.sh
和source script.sh
来调用它。我究竟做错了什么?
当别名被扩展时,这可能是的问题。 bash手册页有以下说:
关于别名的定义和使用的规则有点 混乱。在执行该行上的任何命令之前,Bash总是读取至少一个完整的输入行。读取命令 时不扩展别名,而不是在执行时。 ...
有手册页的详细信息,但在执行一个复合语句,如您while
循环内的列表时,当输入是第一次读的时候,而不是在执行时会发生膨胀。由于GIT
在输入读取时未定义,因此会出现错误。
以下片段展示了这个问题:
#!/bin/bash
shopt -s expand_aliases
while read x; do
a=`echo $x | tr '[:lower:]' '[:upper:]'`
alias $a=$x
GIT # <--- this fails to execute git
done < <(echo 'git')
GIT # <--- this executes git
一旦while循环已经执行,那么别名变为可用。手册页中的详细信息有点粗略,但看起来就好像在函数中定义的别名注释一样。
另外,使用诸如echo foo | while read x; do stuff; done
等语法时要小心。 while
循环将在子shell中执行,在子shell中所做的任何更改将不会持续超出while
循环。上面的例子显示了一个方法,以便while循环在当前shell中执行,但是从执行的命令获取其输入。
更新:
如果上面的脚本写在它的原始形式,它应该是这样的:
#!/bin/bash
shopt -s expand_aliases
#Currently just using 'git' to try and get it working
#It'll be replaced with the following line when it works
#compgen -c | while read x;
echo 'git' | while read x; do
a=`echo $x | tr '[:lower:]' '[:upper:]'`
alias $a=$x
GIT # <--- this fails to execute git
done
GIT # <--- this also fails executes git because the alias' were set in a subshell.
在这种情况下,永远不会执行的别名。原因在于管道|
带来了一个新的子shell并将这些进程链接在一起。 echo
在一个过程中运行,while read ...
在另一个过程中运行,通过管道链接。当别名被设置时,它们被设置在运行while
循环的子shell的进程的环境中。但是,当while
循环结束时,该进程将终止并丢弃其环境,同时对其环境进行任何更改(例如添加别名)。因此,第二次尝试执行GIT
将失败,因为别名信息已被丢弃。
当您使用第一个脚本中显示的拓扑时,while
循环会在当前脚本中运行,因此对环境所做的任何更改都会持续到循环结束。
如果您的脚本执行而不是采购它,您也会注意到此行为。如果您希望能够像这样在脚本中配置一组别名,请运行该脚本,让它们在您的环境中可用,您也会遇到同样的问题,因为您的脚本在父shell的独立进程中运行,创建别名,这些脚本随后在脚本退出时被丢弃。
$ ./create_aliases
$ alias # <--- Ooops, no aliases defined.
您必须像这样来源脚本,它将运行当前进程中脚本的内容,从而修改当前环境。
$ source ./create_aliases
$ alias # <--- Yay, new aliases present.
这就是为什么bash将源文件如~/.bashrc
,这样改变了你在该文件中作出将在当前环境中存在。
优秀!我认为这可能与子shell有关,但无法弄清楚(对于bash脚本来说是非常新颖的)。你能否详细解释一下' SomeKittens 2013-04-10 13:24:03
@SomeKittens答案更新。 – 2013-04-10 23:41:02
你不应该依赖脚本中的别名。你应该直接使用变量。但如果你仍然想要别名,也许这可以帮助:http://*.com/questions/5240755/how-to-use-aliases-defined-in-bashrc-in-shell-script – Lynch 2013-04-10 03:27:29
脚本的整个观点是*设置别名,不运行它。这有点无用,但很有趣! – SomeKittens 2013-04-10 13:21:34