命令建议是如何在 bash shell 中实现的?
Posted
技术标签:
【中文标题】命令建议是如何在 bash shell 中实现的?【英文标题】:How is the command suggestion implemented in the bash shell? 【发布时间】:2016-06-13 06:26:33 【问题描述】: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
我目前已经实现了一个简单的“你的意思是......?”对于简单的英语单词,其工作方式如下:
如果用户输入“Kack”,请在 QWERTY 键盘上检查单词中每个字母周围的字母并逐一替换。 (例如,在这里它们将是 J、L、M、I、O 代表“K”;Q、W、S、Z、X 代表“a”等等) 根据对文本语料库的训练,返回最有可能的词(如果是这种情况,用户也输入了词本身)作为最有可能的词。linux命令行中的代码建议是如何实现的?
【问题讨论】:
【参考方案1】: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 -- "$1";
return $?;
else
if [ -x /usr/share/command-not-found/command-not-found ]; then
/usr/share/command-not-found/command-not-found -- "$1";
return $?;
else
printf "%s: command not found\n" "$1" 1>&2;
return 127;
fi;
fi
(并且/usr/lib/command-not-found
存在,可执行,并且是 Python 脚本。)
【讨论】:
谢谢!你是怎么知道的?我的意思是更一般地说,如果没有 SO,我怎么会发现从 CLI 中调用的函数? @Ketcomp:阅读man bash
。 (在COMMAND EXECUTION
部分的第三段中。)【参考方案2】:
来自 Bash 手册页:
命令执行
[…]
如果名称既不是 shell 函数也不是内置函数,并且不包含斜杠,bash 会在
PATH
的每个元素中搜索包含该名称的可执行文件的目录。 Bash 使用哈希表来记住可执行文件的完整路径名(请参阅下面的 SHELL BUILTIN COMMANDS 下的hash
)。仅当在哈希表中找不到该命令时,才会对PATH
中的目录进行完整搜索。如果搜索不成功,shell 将搜索一个已定义的名为command_not_found_handle
的 shell 函数。如果该函数存在,则使用原始命令和原始命令的参数作为其参数调用它,并且该函数的退出状态变为 shell 的退出状态。如果未定义该函数,shell 会打印一条错误消息并返回退出状态 127。
让我们试试这个:
$ foobar bash:foobar:找不到命令 $ function command_not_found_handle echo "我很抱歉,'$1' 是什么?"; $ foobar 对不起,什么是'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 "$1"
else
echo "$1: Command not found" >&2
return 127
fi
这样,以后再次安装或删除command-not-found
包时,无需更改配置文件。
我不知道 Ubuntu 的程序是如何实现的,但通常,这样的工具会列出所有已知命令并找到最相似的命令。然后它可能会检查该程序是否已安装,如果没有,则检查提供它的软件包并建议安装。
搜索“相似文本”通常是通过计算两个字符串之间的edit distance 来完成的。考虑到给定字母的错误输入可能性,考虑到当前的键盘布局,这将是一个非常明智的补充。
【讨论】:
在 rici 的回答之后,我尝试使用 grep 在手册页中查找这些相关数据。但是后来你发布了这个;) +1 用于函数的内联重新定义以更好地说明逻辑! @Ketcomp:在man bash
(或man
任何内容)中,您可以通过键入/
后跟要搜索的字符串进行搜索,假设您使用的是less
作为您的寻呼机。 h
将为您提供可能的less
命令的摘要。你会发现这比grep
更容易。以上是关于命令建议是如何在 bash shell 中实现的?的主要内容,如果未能解决你的问题,请参考以下文章
如何在bash shell中执行for循环生成的curl命令?
如何在 Python 中实现常见的 bash 习语? [关闭]