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 为此使用了 readline,您为什么不考虑自己使用它呢?我不太了解它,对不起,但我认为它可能会有所帮助。

于 2011-04-11T12:04:31.847 回答
1

我认为这不能足够快地在纯 bash 中交互使用(也许使用complete内置?)。也就是说,您可以尝试简化您正在使用的命令。您可以对所有单词使用一个,而不是grep每个单词一个,方法是

  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 回答