通常,如果我在 bash(在 macOS 上)中工作,我也会在 (Mac)Vim 中工作,在两者之间切换。从 Vim 切换到终端后我常犯的一个错误是在命令前包含一个前导冒号。我将:cd /path/to/project/dir/
在 Vim 中,然后切换到终端并输入完全相同的内容,当然,我不应该在那里以冒号开头。
所以,我不知道什么时候 bash 命令应该以冒号开头,并且每次我我不是故意的。那么,有没有办法让 bash 完全忽略冒号(如果它是命令中的第一个字符)并将其解释:cd ...
为cd ...
?
答案1
bash(1)
command_not_found_handle()
如果已定义并且未找到要执行的命令,则将调用该函数。如果您尚未使用此功能(例如 Ubuntu 上的 command-not-found 软件包),您可以使用它来去掉冒号并重试:
command_not_found_handle() {
if [[ "${1:0:1}" != : ]]; then
printf "%s: %s: command not found\n" "$0" "$1" >&2
return 127
else
"${1/#:}" "${@:2}"
fi
}
将该函数放入您的.bashrc
.然后,当未找到以冒号开头的命令时,它将去掉前面的冒号并重试。
编辑:我会进一步解释一下,因为这里有一些不常见的扩展。
首先,正如评论中所指出的,command_not_found_handle
这是 bash 4 的一个功能。 Bash 4 于 2009 年 2 月发布。command_not_found_handle
使用未找到的命令和该命令的参数来调用该函数。 ie$1
是未找到的命令,$2
之后是未找到的命令的参数。这在下面描述命令执行在手册页中。
"${1:0:1}"
是一个扩展,它从 , 从位置 0 开始长度为 1 的子字符串$1
。也就是说,它从 中提取第一个字符$1
,其中$1
是未找到的命令。这记录在参数扩展在手册页中为${parameter:offset:length}
.
如果 的第一个字符$1
不是冒号,我们会打印一个错误并返回退出值 127。 127 是 bash 在找不到要执行的命令时使用的退出代码,如下所示命令执行在手册页中。
"${1/#:}"
扩展为$1
并去掉任何前导冒号。如果开头没有冒号,则它相当于一个普通的$1
,但由于我们所处的条件的分支,我们知道它无论如何都以冒号开头。此扩展记录在参数扩展在手册页中的${parameter/pattern/string}
部分中。
"${@:2}"
从第二个开始扩展到位置参数。此扩展记录在参数扩展在手册页中的${parameter:offset}
部分,作为数组和 的特殊情况@
。也就是说,它不是提取子字符串,而是扩展到数组的元素。
最终结果是,如果运行未找到的命令并且该命令有一个前导冒号,我们将去掉冒号以形成一个新命令,并将原始参数传递给新命令。这最终将以递归方式工作,就好像未找到第二次运行命令的尝试一样,command_not_found_handle()
将再次执行。这意味着您可以运行:::mkdir
并且它仍然会运行mkdir
。