微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在bash脚本中设置别名

我正在尝试在脚本中创建一个别名,如下所示:

#!/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.我究竟做错了什么?

解决方法

这可能是别名扩展时的问题. bash手册页有以下内容

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.

这就是为什么bash将提供诸如〜/ .bashrc之类的文件,以便您在该文件中所做的更改将存在于当前环境中.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐