根据索引从字符串中抓取一个单词的更有效方法?

根据索引从字符串中抓取一个单词的更有效方法?

我正在尝试编写一个 Bash 完成脚本,该脚本在存在冒号的情况下不会中断。为此,我使用 COMP_LINE 来确定命令的字符串,并使用 COMP_POINT 作为用户当前指向命令中哪个字符的索引。

使用这两个变量,我想计算出用户当前正在尝试完成哪个单词。这通常使用 COMP_WORDS 数组来完成,其中 COMP_CWORD 变量充当指向该数组的指针。问题是,COMP_WORDS 在冒号上分割字符串,因此命令如下:

dothis foo:bar

读入 COMP_WORDS 为:

('dothis' 'foo' ':' 'bar')

我不想要这种行为,所以我正在解决它。

假设我有一个命令存储在 Bash 变量中,如下所示:

apple banana carrot:cucumber  durian

我目前对上述问题的解决方案如下。解释在代码下面,老实说我认为代码更简单。

#!/bin/bash

str="apple banana carrot:cucumber  durian"
cur=29
char=${str:$cur:1} # Current character being pointed to
prev=${str:$cur-1:1} # Previous character

if [[ $char == [[:space:]] ]]; then
    if [[ $prev == [[:space:]] ]]; then
        # Rule 1 - Char and prev are whitespace
        # apple banana carrot:cucumber  durian
        #                              ^ Char = ' ' Prev = ' '
        word=""
    else
        # Rule 2 - Char is whitespace, prev is not
        # apple banana
        #      ^ Char = ' ' Prev = 'e'
        # Means prev is the last character of the word
        slice="${str::$cur}"
        word="${slice##* }" # 'apple'
    fi
else
    if [[ $prev == [[:space:]] ]]; then
        # Rule 3 - Char is not whitespace, prev is whitespace
        # apple banana carrot:cucumber
        #              ^ Char = 'c' Prev = ' '
        slice="${str:$cur}"
        word="${slice%% *}" # 'carrot:cucumber'
    else
        # Rule 4 - Char and prev are not whitespace
        # apple banana
        #          ^ Char = 'a' Prev = 'n'
        end="${str:$cur}"
        end="${end#* }"
        slice="${str% $end}"
        word="${slice##* }" # 'banana'
    fi
fi
echo "Word: <$word>"

其作用如下。它检查索引处的字符 (char) 及其之前的字符 (prev),并遵循以下四个规则来确定当前指向哪个单词:

  1. 如果 char 和 prev 都是空白字符,则将 'word' 设置为空

  2. 如果 char 是空格但 prev 是非空格字符,则将 'prev' 作为单词的结尾。提取一个子字符串直到 prev,然后删除从该子字符串开头到(包括空格)的所有内容。

  3. 如果 char 是非空白字符但 prev 是空白,则将 'char' 作为单词的开头。提取直到 prev 的子字符串,然后删除从子字符串末尾直到(包括空格)的所有内容。

  4. 如果 char 和 prev 都是非空白字符,则将 'char' 视为单词的中间或结尾。首先抓取从“char”到字符串末尾的子字符串,然后从该子字符串的开头删除最短的文本实例,直到包含空格。然后删除从原始字符串中提取子字符串,以获取单词的所有内容。最后来自子字符串,删除所有内容(包括空格)以获取单词。


基本上我不相信这是最有效的解决方案。即使用问题来描述也很复杂。当然有一些更好、更奇特的方法可以根据该单词的索引从字符串中获取整个单词?

任何人都可以提供关于解决此问题的更好方法的建议,或者如果没有,有什么方法可以优化我的解决方案吗?

相关内容