为什么别名在里面不起作用?

Kei*_*iji 6 bash alias

.bashrc设置了一堆别名供我根据需要使用,然后自动运行其中一个。

事实证明,与使用交互式 shell 相比,这会导致自动脚本 ssh 进入我的机器时出现一些问题。所以,为了解决这个问题,我把它们放在一个 if 块中,这样它们就不会被定义或运行那些自动化脚本......

if [ -n "$TERM" ] && [ "$TERM" != "dumb" ] ; then
    alias short='long command here'
    alias another='very long command here'
    # ...

    short
fi
Run Code Online (Sandbox Code Playgroud)

只为看short: command not found

让我们将其减少到最低限度......

$ cat alias.sh
alias foo='echo hi'
foo
Run Code Online (Sandbox Code Playgroud)
$ sh alias.sh
hi
Run Code Online (Sandbox Code Playgroud)
cat alias-in-if.sh
if true ; then
        alias foo='echo hi'
        foo
fi
Run Code Online (Sandbox Code Playgroud)
sh alias-in-if.sh
alias-in-if.sh: line 3: foo: command not found
Run Code Online (Sandbox Code Playgroud)

为什么第一个脚本有效,而不是第二个?

(我已经回答了我自己的问题。)

Kei*_*iji 6

我四处搜索,没有发现与 ifs 内的别名有关的任何内容,只有函数内的别名,这起初似乎是一个不同的问题。

但实际上,这个答案解决了这个问题:

在执行该行上的任何命令之前,Bash 总是至少读取一整行输入。[...] 该行上别名定义后面的命令不受新别名的影响。[...] 为了安全起见,请始终将别名定义放在单独的行上,并且不要在复合命令中使用别名。

似乎这不仅限于函数,还包括 if 语句。整个 if 块被视为一行。为了确保仅在条件为 true 时定义并执行别名,但确保在条件为 false 时甚至不定义别名,解决方案是像这样评估条件两次:

cat alias-before-if.sh
if true ; then
        alias foo='echo hi'
fi

if true; then
        foo
fi
Run Code Online (Sandbox Code Playgroud)
$ sh alias-before-if.sh
hi
Run Code Online (Sandbox Code Playgroud)

所以我原来的脚本是:

if [ -n "$TERM" ] && [ "$TERM" != "dumb" ] ; then
    alias short='long command here'
    alias another='very long command here'
    # ...
fi

if [ -n "$TERM" ] && [ "$TERM" != "dumb" ] ; then
    short
fi
Run Code Online (Sandbox Code Playgroud)

  • 不要对情况进行两次评估。评估一次,保存结果并使用结果两次。这不仅是[DRY](https://en.wikipedia.org/wiki/Don't_repeat_yourself);一般来说,如果条件取决于时间、文件的存在、任何外部因素,该方法将避免(至少是一些)错误,因此每次都可以进行不同的评估。 (2认同)