2016-03-01 4 views
2
[email protected]:~$ 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 

J'ai actuellement implémenté un simple 'Did you mean ..?' pour les mots anglais simples qui fonctionne comme suit:Comment la suggestion de commande est-elle implémentée dans le shell bash?

  • Si l'utilisateur entre « Kack », vérifiez les alphabets autour de chaque alphabet dans le mot sur un clavier QWERTY et les remplacer par un par un. (par exemple ici ils seraient J, L, M, I, O pour 'K', Q, W, S, Z, X pour 'a' et ainsi de suite)
  • Retourne le mot avec le plus de probabilité (l'utilisateur mot entré lui-même aussi si c'est le cas) comme le mot le plus probable basé sur la formation sur un corpus de texte.

Comment la suggestion de code est-elle implémentée dans la ligne de commande linux?

Répondre

5

bash n'implémente pas la logique de suggestion; il est dans une fonction définie dans le cadre de votre fichier d'initialisation de bash, et il a été placé là par votre distribution (Ubuntu/Debian, à la conjecture).

bash fournit le mécanisme pour implémenter une telle fonction: quand il tente d'exécuter une commande, et la commande est introuvable, il appelle la fonction command_not_found_handle, si elle est définie.

Sur ma machine (une variante d'Ubuntu), cette fonction est définie comme suit:

$ 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 
} 

(Et /usr/lib/command-not-found existe, est exécutable, et est un script Python.)

+0

Merci! Comment le savais-tu? Je veux dire d'une manière plus générale, disons sans SO, comment aurais-je découvert quelle fonction est appelée par exemple, juste la CLI? – Ketcomp

+1

@Ketcomp: Lire 'man bash'. (C'est dans le troisième paragraphe de la section «COMMAND EXECUTION».) – rici

1

de l'homme Bash page:

COMMANDE EXECUTION

[...]

Si le nom n'est ni une fonction shell ni un élément intégré et ne contient aucune barre oblique, bash recherche dans chaque élément du PATH un répertoire contenant un fichier exécutable portant ce nom. Bash utilise une table de hachage pour se souvenir des chemins complets des fichiers exécutables (voir hash sous COMMANDES SHELL BUILTIN ci-dessous). Une recherche complète des répertoires dans PATH est effectuée uniquement si la commande n'est pas trouvée dans la table de hachage. Si la recherche échoue, le shell recherche une fonction shell définie nommée command_not_found_handle. Si cette fonction existe, elle est invoquée avec la commande d'origine et les arguments de la commande d'origine comme arguments, et le statut de sortie de la fonction devient le statut de sortie du shell. Si cette fonction n'est pas définie, le shell affiche un message d'erreur et renvoie un état de sortie de 127.

Essayons ceci:

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

Votre code d'initialisation du shell peut installer un plus utile command_not_found_handle. Vous trouverez généralement ce type de code dans la configuration à l'échelle du système au /etc/bash.bashrc ou dans un fichier provenant de celui-ci. Votre distribution peut y installer un gestionnaire pour appeler un programme externe qui interroge le gestionnaire de paquets de la distribution pour la commande ou les commandes "similaires". Pour votre Ubuntu, ceci serait implémenté dans le command-not-found package.Les fichiers de configuration par défaut fournis par les distributions sont généralement très généraux. La fonction peut donc vérifier si le fichier binaire command-not-found est installé et, le cas échéant, l'appeler ou afficher un message d'erreur simple.

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 
} 

De cette façon, le fichier de configuration ne doit pas être changé si le paquet command-not-found est installé ou enlevé plus tard.

Je ne sais pas comment ce programme pour Ubuntu est implémenté mais typiquement, un tel outil aurait une liste de toutes les commandes connues et en trouverait la plus similaire. Il peut alors vérifier si ce programme est installé et, si ce n'est pas le cas, vérifier quel paquet le fournit et suggérer d'installer celui-ci.

La recherche de "texte similaire" est généralement effectuée en calculant le edit distance entre deux chaînes. Tenir compte de la probabilité de fautes de frappe d'une lettre donnée, étant donné la disposition actuelle du clavier, serait un ajout très intelligent.

+0

Après la réponse de rici, j'essayais d'utiliser grep pour trouver ces données pertinentes dans les pages man. Mais alors vous avez posté ceci;) +1 pour la redéfinition en ligne de la fonction pour mieux illustrer la logique! – Ketcomp

+2

@Ketcomp: Dans 'man bash' (ou dans' man' n'importe quoi), vous pouvez rechercher en tapant '/' suivi de la chaîne que vous voulez rechercher, en supposant que vous utilisez 'less' comme pager. 'h' vous donnera un résumé des commandes' less' possibles. Vous trouverez cela plus facile que 'grep'. – rici