2

逆検索履歴が機能するのと同じ方法でファイルを検索する関数を作成しようとしています。つまり、ユーザーが入力を開始し、プロンプトが最初の一致で更新され、特別なキーを押すと他の一致が順番に回転し、別の特別なキーを押すと現在の一致が選択されます。

これに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
4

2 に答える 2

1

これは、純粋な bash でインタラクティブに使用するのに十分な速度にできるとは思いません (おそらくビルトインを使用しcompleteますか?)。そうは言っても、使用しているコマンドを単純化してみることができます。単語ごとに 1 つではなくgrep、すべての単語に 1 つを使用できます。

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

代わりにhead -$matchNumber | tail -1を使用できますsed -n ${matchNumber}{p;q}

于 2011-04-11T18:41:17.120 に答える
1

bash はこれに readline を使用していると思いますが、自分で使用してみませんか? 申し訳ありませんが、それについてはあまり知りませんが、役立つかもしれないと思いました。

于 2011-04-11T12:04:31.847 に答える