逆検索履歴が機能するのと同じ方法でファイルを検索する関数を作成しようとしています。つまり、ユーザーが入力を開始し、プロンプトが最初の一致で更新され、特別なキーを押すと他の一致が順番に回転し、別の特別なキーを押すと現在の一致が選択されます。
これにbashスクリプトを書きましたが、非常に遅いです。これを高速化するために他のUNIX/bash機能を利用できるかどうか疑問に思っていました。多分awkを使用していますか?
任意のアイデアをいただければ幸いです。
このスクリプトでは、TABが一致をローテーションし、ENTERが現在の一致を選択し、ESCが終了し、BACKSPACEが現在の検索の最後の文字を削除します。(私の危険なbashスクリプトを許してください、bash / unixは比較的新しいです)
#!/bin/bash
do_search()
{
#Record the current screen position
tput sc
local searchTerm
local matchNumber=1
local totalSearchString
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 [ "$totalSearchString" != "" ]; then
totalSearchString=${totalSearchString%?}
fi
#If ESCAPE
elif [ "$char" == "" ]; then
tput el1
tput rc
return 0
#If TAB
elif [ "$char" == "$TAB_CHAR" ]; then
matchNumber=$(($matchNumber+1))
#OTHERWISE
else
totalSearchString="$totalSearchString$char"
fi
match=""
if [ "$totalSearchString" != "" ]; then
#This builds up a list of grep statements piping into each other for each word in the totalSearchString
#e.g. totalSearchString="blah" will output "| grep blah"
#e.g. totalSearchString="blah1 blah2" will output "| grep blah1 | grep blah2"
local grepStatements=`echo $totalSearchString | 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) '$totalSearchString': $match"
done
return 0
}
do_search categories.txt