#!/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显示在别名中,但无法执行.我试过用它来试试. ./script.sh和source script.sh.我究竟做错了什么?
解决方法
The rules concerning the deFinition and use of aliases are somewhat
confusing. Bash always reads at least one complete line of input before executing any of the commands on that line. Aliases are expanded when a command
is read,not when it is executed. …
手册页中有更多信息,但在执行复合语句(例如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 |等语法时要小心读x;做东西;完成. 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读取…在另一个进程中运行,由管道链接.设置别名后,它们将在运行while循环的子shell的进程环境中设置.但是,当while循环结束时,该进程将终止并丢弃其环境,以及对其环境所做的任何更改,例如添加别名.结果,执行GIT的第二次尝试将失败,因为别名信息已被丢弃.
当您使用第一个脚本中显示的拓扑时,while循环在当前脚本中运行,因此对环境所做的任何更改都会在循环结束后保持不变.
如果您执行脚本而不是获取脚本,您还会注意到此行为.如果您希望能够在这样的脚本中配置一组别名,运行脚本,让它们在您的环境中可用,您遇到同样的问题,因为您的脚本在一个单独的进程中运行到父shell,创建别名,当脚本退出时随后被丢弃.
$./create_aliases $alias # <--- Ooops,no aliases defined.
您必须像这样来源脚本,它将在当前进程中运行脚本的内容,从而修改当前环境.
$source ./create_aliases $alias # <--- Yay,new aliases present.