bashshell中的命令建议是如何实现的?

How is the command suggestion implemented in the bash shell?

gk@Jarvis:~$ sudi
No command 'sudi' found, did you mean:
Command 'sudo' from package 'sudo-ldap' (universe)
Command 'sudo' from package 'sudo' (main)
sudi: command not found

我目前已经为简单的英语单词实现了一个简单的 'Did you mean..?',其工作原理如下:

如何在 linux 命令行中实现代码建议?

bash没有实现建议逻辑;它位于定义为 bash 初始化文件的一部分的函数中,并且由您的分发版(Ubuntu/Debian 猜测)放在那里。

bash 提供了实现这样一个函数的机制:当它试图执行一个命令,但没有找到该命令时,它会调用函数 command_not_found_handle,如果它被定义的话。

在我的机器上(Ubuntu 变体),该函数定义如下:

$ type command_not_found_handle
command_not_found_handle is a function
command_not_found_handle () 
{ 
    if [ -x /usr/lib/command-not-found ]; then
        /usr/lib/command-not-found -- "";
        return $?;
    else
        if [ -x /usr/share/command-not-found/command-not-found ]; then
            /usr/share/command-not-found/command-not-found -- "";
            return $?;
        else
            printf "%s: command not found\n" "" 1>&2;
            return 127;
        fi;
    fi
}

(并且 /usr/lib/command-not-found 存在,可执行,并且是一个 Python 脚本。)

来自 Bash 手册页:

COMMAND EXECUTION

[…]

If the name is neither a shell function nor a builtin, and contains no slashes, bash searches each element of the PATH for a directory containing an executable file by that name. Bash uses a hash table to remember the full pathnames of executable files (see hash under SHELL BUILTIN COMMANDS below). A full search of the directories in PATH is performed only if the command is not found in the hash table. If the search is unsuccessful, the shell searches for a defined shell function named command_not_found_handle. If that function exists, it is invoked with the original command and the original command's arguments as its arguments, and the function's exit status becomes the exit status of the shell. If that function is not defined, the shell prints an error message and returns an exit status of 127.

让我们试试看:

$ foobar
bash: foobar: command not found
$ function command_not_found_handle { echo "I'm so sorry, what is ''?"; }
$ foobar
I'm so sorry, what is 'foobar'?

您的 shell 初始化代码可能会安装更有用的 command_not_found_handle。您通常会在 /etc/bash.bashrc 中的系统范围配置或由它获取的文件中找到此类代码。您的发行版可能会在那里安装一个处理程序来调用一个外部程序,该程序向发行版的包管理器查询命令或“类似”命令。对于您的 Ubuntu,这将在 command-not-found package.

中实现

发行版提供的默认配置文件通常非常通用,因此该函数可能会检查是否安装了 command-not-found 二进制文件,如果安装了,则调用它或以其他方式打印一条简单的错误消息。

function command_not_found_handle {
    if [ -x /usr/bin/command-not-found ]
    then
        /usr/bin/command-not-found ""
    else
        echo ": Command not found" >&2
        return 127
    fi
}

这样,如果稍后再次安装或删除 command-not-found 包,则不必更改配置文件。

我不知道 Ubuntu 的程序是如何实现的,但通常,这样的工具会列出所有已知命令并找到最相似的命令。然后它可能会检查是否安装了该程序,如果没有,检查提供它的软件包并建议安装它。

搜索“相似文本”通常是通过计算两个字符串之间的 edit distance 来完成的。考虑到给定字母输入错误的可能性,考虑到当前的键盘布局,将是一个非常明智的补充。