设置别名

设置别名

问题描述:

我想在一个脚本来创建一个别名,像这样:设置别名

#!/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.shsource script.sh来调用它。我究竟做错了什么?

+1

你不应该依赖脚本中的别名。你应该直接使用变量。但如果你仍然想要别名,也许这可以帮助:http://*.com/questions/5240755/how-to-use-aliases-defined-in-bashrc-in-shell-script – Lynch 2013-04-10 03:27:29

+0

脚本的整个观点是*设置别名,不运行它。这有点无用,但很有趣! – SomeKittens 2013-04-10 13:21:34

当别名被扩展时,这可能是的问题。 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,这样改变了你在该文件中作出将在当前环境中存在。

+0

优秀!我认为这可能与子shell有关,但无法弄清楚(对于bash脚本来说是非常新颖的)。你能否详细解释一下' SomeKittens 2013-04-10 13:24:03

+1

@SomeKittens答案更新。 – 2013-04-10 23:41:02