8

有没有办法指定一个特定的命令不区分大小写,而不需要全局打开不区分大小写(至少对于那个 shell)?

在我的特殊情况下,我有一个小应用程序,它可以让我通过命令行访问电子邮件地址数据库,所以我输入:

db get email john smith

并返回 John Smith 的电子邮件地址。所以我设法在应用程序内部启用了完成功能:设置

COMPREPLY=($(compgen -W "$(db --complete $COMP_CWORD "$COMP_WORDS[@]"}")" -- ${COMP_WORDS[COMP_CWORD]}))

可以让我完成制表符getemail. 但是,如果我然后键入j<tab>,它会拒绝,因为在电子邮件数据库中,它是正确大写的。无论如何,我想让 bash 完成这项工作。(如果我使用大写字母J,它可以工作。)

如果做不到这一点,我想我可以让我的--complete选项通过匹配输入来更改其回复的大小写,但理想情况下,如果可能的话,命令行将匹配数据库。

请注意,当使用 readline 时,我在应用程序中进行了此操作,它仅与 bash 交互,这似乎是一个问题。

4

2 回答 2

6

事实上,似乎没有办法compgen对单词列表 ( ) 进行不区分大小写的匹配-W。我看到以下解决方法:

简单的解决方案:首先将单词列表和输入标记都翻译成全小写。注意:这只是一个选项,如果可以接受所有完成变成全小写

complete_lower() {

    local token=${COMP_WORDS[$COMP_CWORD]}
    local words=$( db --complete $COMP_CWORD "${COMP_WORDS[@]}" )

    # Translate both the word list and the token to all-lowercase.
    local wordsLower=$( printf %s "$words" | tr [:upper:] [:lower:] )
    local tokenLower=$( printf %s "$token" | tr [:upper:] [:lower:] )

    COMPREPLY=($(compgen -W "$wordsLower" -- "$tokenLower"))   
}

更好但更精细的解决方案:滚动您自己的不区分大小写的匹配逻辑:

complete_custommatch() {

    local token=${COMP_WORDS[$COMP_CWORD]}
    local words=$( db --complete $COMP_CWORD "${COMP_WORDS[@]}" )

    # Turn case-insensitive matching temporarily on, if necessary.
    local nocasematchWasOff=0
    shopt nocasematch >/dev/null || nocasematchWasOff=1
    (( nocasematchWasOff )) && shopt -s nocasematch

    # Loop over words in list and search for case-insensitive prefix match.
    local w matches=()
    for w in $words; do
        if [[ "$w" == "$token"* ]]; then matches+=("$w"); fi
    done

    # Restore state of 'nocasematch' option, if necessary.
    (( nocasematchWasOff )) && shopt -u nocasematch

    COMPREPLY=("${matches[@]}")
}
于 2012-06-11T14:18:14.917 回答
0

grep使用它来完成所有工作要容易得多;然后案件被保留在完成中,你不必弄乱shopt或类似的事情。例如:

_example_completions () {
    local choices="john JAMES Jerry Erik eMIly alex Don donald donny@example.com RON"
    COMPREPLY=( $( echo "$choices" | tr " " "\n" | grep -i "^$2" ) )
}

在这里,$choices是您的单词列表,tr用于将单词之间的空格更改为换行符以便grep理解它们(如果您的单词已经用换行符分隔,则可以省略),该-i选项不区分大小写匹配,并"^$2"匹配当前单词( bash$2在一行的开头将它作为 ) 传递。

$ example dO<tab>
Don     donald     donny@example.com
于 2020-12-23T05:58:42.463 回答