rechercher dans un fichier dans le style de bash reverse-search-history

J’essaie d’écrire une fonction qui cherche dans un fichier de la même manière que l’historique des recherches inversées. c.-à-d. l’utilisateur commence à taper, l’invite est mise à jour avec le 1er match, bash une clé spéciale fait pivoter d’autres matchs, bash une autre touche spéciale sélectionne le match actuel.

J’ai écrit un script bash à cela, mais il est terriblement lent. Je me demandais si je pouvais exploiter une autre fonctionnalité Unix / Bash pour faire cela rapidement. Peut-être en utilisant awk?

Toute idée serait appréciée.

Pour ce script, TAB fait pivoter les correspondances, ENTER sélectionne la correspondance actuelle, ESC se termine, BACKSPACE supprime le dernier caractère de la recherche en cours. (pardonne mon script douteux bash, je suis relativement nouveau à bash / unix)

#!/bin/bash do_search() { #Record the current screen position tput sc local searchTerm local matchNumber=1 local totalSearchSsortingng local TAB_CHAR=`echo -e "\t"` #print initial prompt echo -n "(search) '':" #-s: means input will not be echoed to screen, -n1 means that one character will be gotten while IFS= read -r -s -n1 char do #If ENTER if [ "$char" == "" ]; then if [ "$match" != "" ]; then eval "$match" fi echo "" return 0 #If BACKSPACE elif [ "$char" == "" ]; then if [ "$totalSearchSsortingng" != "" ]; then totalSearchSsortingng=${totalSearchSsortingng%?} fi #If ESCAPE elif [ "$char" == "" ]; then tput el1 tput rc return 0 #If TAB elif [ "$char" == "$TAB_CHAR" ]; then matchNumber=$(($matchNumber+1)) #OTHERWISE else totalSearchSsortingng="$totalSearchSsortingng$char" fi match="" if [ "$totalSearchSsortingng" != "" ]; then #This builds up a list of grep statements piping into each other for each word in the totalSearchSsortingng #eg totalSearchSsortingng="blah" will output "| grep blah" #eg totalSearchSsortingng="blah1 blah2" will output "| grep blah1 | grep blah2" local grepStatements=`echo $totalSearchSsortingng | sed 's/\([^ ]*\) */| grep \1 /g'` local cdHistorySearchStatement="cat $1 $grepStatements | head -$matchNumber | tail -1" #Get the match match=`eval "$cdHistorySearchStatement"` fi #clear the current line tput el1 tput rc #re-print prompt & match echo -n "(search) '$totalSearchSsortingng': $match" done return 0 } do_search categories.txt 

Je pense que bash utilise readline pour cela, pourquoi ne pas envisager de l’utiliser vous-même? Je n’en sais pas beaucoup plus, désolé, mais je pensais que cela pourrait aider.

Je ne pense pas que cela puisse être fait assez rapidement pour une utilisation interactive en pure bash (peut-être en utilisant l’ complete complète?). Cela dit, vous pouvez essayer de simplifier les commandes que vous utilisez. Au lieu d’un grep par mot, vous pouvez en utiliser un pour tous, en faisant

  grepStatements=$(echo "$totalSearchSsortingng" | sed 's/[ ]\+/|/g') cdHistorySearchStatement="grep '$grepStatements' $1 | ..." 

et au lieu de la head -$matchNumber | tail -1 head -$matchNumber | tail -1 vous pouvez utiliser sed -n ${matchNumber}{p;q} .