在bash脚本中设置别名 [英] Set alias within bash script

查看:52
本文介绍了在bash脚本中设置别名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to create an alias in a script like so:

#!/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的别名中):

While a simple test script works (testme is added to the aliases in my current 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 源script.sh .我在做什么错了?

GIT shows up in the aliases, but can't be executed. I've tried calling it with . ./script.sh and source script.sh. What am I doing wrong?

推荐答案

扩展别名时可能会出现问题.bash手册页的内容如下:

It's likely a problem of when the alias is expanded. The bash man page has the following to say:

有关别名的定义和使用的规则有些令人困惑.在执行该行中的任何命令之前,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 ,因此会出现错误.

There's more info in the man page, but when executing a compound statement such as the list within your while loop, the expansion will occur when when the input is first read, not when executed. Since GIT is not defined when the input is read, there will be an error.

以下代码片段显示了该问题:

The following snippet shows the issue:

#!/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循环,则别名变为可用.手册页中的详细信息有些粗略,但似乎似乎适用于在函数中定义的别名的注释.

Once the while loop has executed, then the alias becomes available. Details in the man page are a bit sketchy, but it appears as though the comments for aliases defined in functions would apply.

此外,使用诸如 echo foo |读x时做东西;完成. while 循环将在一个子shell中执行,在子shell中进行的任何更改将不会在 while 循环之外继续存在.上面的示例显示了一种方法,使得while循环在当前shell中执行,但是从执行的命令中获取其输入.

Also, be careful when using syntax such as echo foo | while read x; do stuff; done. The while loop will execute in a subshell, any changes made in the subshell will not persist beyond the while loop. The example above shows a method so that the while loop executes in the current shell, but takes its input from a command which is executed.

更新:

如果以上脚本以原始格式编写,则将如下所示:

If the above script were written in its original form it would look like this:

#!/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.

在这种情况下,永远不会执行别名.这样做的原因是管道 | 为新的子外壳加注星标,并将进程链接在一起. echo 在一个进程中运行,而 while read ... 在另一个进程中运行,通过管道链接.设置别名后,将在运行 while 循环的子shell进程的环境中设置别名.但是,当 while 循环完成时,该过程终止,其环境以及对其环境所做的任何更改(例如添加别名)都将被丢弃.结果,由于别名信息已被丢弃,第二次执行 GIT 的尝试将失败.

In this case, the alias is never executed. The reason for this is that the pipe | stars a new subshell and links the processes together. The echo runs in one process, the while read ... runs in the other, linked by a pipe. When the aliases are set, they are set in the environment of the process of the subshell running the while loop. However, when the while loop has finished, that process terminates and its environment is discarded, along with any changes made to its environment such as the addition of aliases. As a result, the second attempt to execute GIT will fail as the alias information has been discarded.

使用第一个脚本中显示的拓扑时, while 循环将在当前脚本中运行,因此对环境所做的任何更改都会在循环结束后继续存在.

When you use the topology shown in the first script, the while loops runs in the current script, so any changes made to the environment persist past the end of the loop.

如果您执行脚本而不是采购脚本,您还将注意到此行为.如果您希望能够在这样的脚本中配置一组别名,运行该脚本,使其在您的环境中可用,那么您会遇到同样的问题,因为您的脚本在与父外壳程序不同的进程中运行,创建了别名,然后在脚本退出时将其丢弃.

You will also notice this behaviour if you execute your script, rather than sourcing it. If you expect to be able to configure a set of aliases in a script like this, run the script, have them available in your environment, you have the same problem because your script runs in a separate process to the parent shell, creates the aliases, which are subsequently discarded when the script exits.

$ ./create_aliases
$ alias  # <--- Ooops, no aliases defined.

您必须像这样来获取脚本,该脚本将在当前进程中运行脚本的内容,从而修改当前环境.

You'd have to source your script like this, which will run the contents of the script in the current process, thus modifying the current environment.

$ source ./create_aliases
$ alias # <--- Yay, new aliases present.

这就是为什么bash将源文件如〜/.bashrc 的原因,以便您在该文件中所做的更改将在当前环境中存在.

This is why bash will source files such as ~/.bashrc, so that changes you make in that file will exist in the current environment.

这篇关于在bash脚本中设置别名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆