【问题标题】:Override of "select" builtin覆盖“选择”内置
【发布时间】:2020-03-08 17:42:17
【问题描述】:

最近我尝试覆盖三个常用命令:

  • 睡觉
  • 等一下
  • 选择

第一个(sleep)通常是一个外部 bin(在我的 Debian 10 中为/bin/sleep)。 第二个(wait)是内置的(你可以用command -v wait检查它)。 第三个(select)也是内置的。

我会写一些例子来复现哪些有效,哪些无效,请耐心等待。

覆盖sleepwait 没有问题,我只是在代码的某处添加了以下内容:

sleep() {
  echo using custom sleep
}
wait() {
  echo using custom wait
}

当我尝试覆盖 select 时,情况发生了变化。

特别是,如果我尝试像上面那样创建一个简单的函数,我会收到错误,因为解析器 (?) 认为我正在尝试使用该命令而不是创建一个新函数。

您可以通过以下方式重现错误:

#!/bin/bash
select() {
  echo using custom select
}

使用 function select() { 符号可以避免这种情况。

如果我使用的是交互式 shell,我可以使用 别名 解决问题;重现步骤:

_select() { echo using custom select;}
alias select='_select'
select

但是如果我使用文件,此解决方案将不起作用。

让我们尝试一下:

#!/bin/bash
# this is the actual script
. lib.sh
select

...和:

#!/bin/bash
# this is where I declare the function select
_select() {
  echo using custom select
}
alias select='_select'

如果我运行script,而后者又是lib.sh,当我尝试调用我的别名时会出错。

对我来说,这是第一次,别名是内置函数之后的“第二选择”。

是我做错了什么还是这是一个实际的“错误”?

显然,一种解决方法是将函数重命名为其他名称。

【问题讨论】:

  • 顺便说一句。 select 是关键字,没有内置关键字。
  • @Cyrus 感谢您的这种区别,我搜索了关键字和内置函数之间的差异,它确实解决了我的疑问。特别是,我发现在 bash 解析的早期就扫描了关键字,这就是原因。此外,使用type selectcommand -v select 确定这一点要好得多。如果您愿意,请给出实际答案,我会将其标记为正确的。

标签: bash function alias keyword undefined-behavior


【解决方案1】:

来自bash 手册页的ALIASES 部分:

除非设置了expand_aliases shell 选项,否则当 shell 不是交互式时,别名不会展开 使用 shopt(参见下面SHELL BUILTIN COMMANDS 下对shopt 的描述)。

任意添加

shopt -s expand_aliases

在首次使用select 之前或将-i 添加到您的shebang

#!/bin/bash -i

用于交互式外壳。

【讨论】:

    猜你喜欢
    • 2012-11-15
    • 1970-01-01
    • 2012-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    相关资源
    最近更新 更多