2012-05-09 3 views
6

특정 명령이 대소 문자를 구분하지 않도록 지정하는 방법이 있습니까? (적어도 해당 셸의 경우) 전체적으로 대소 문자를 구분하지 않도록 설정합니까? 내 특정 경우명령 단위로 bash 완료를위한 대소 문자 구별을 설정하는 방법

, 나는 나에게 이메일 주소의 데이터베이스에 대한 명령 줄 액세스를 제공하는 작은 응용 프로그램을 가지고, 그래서 입력 :

db get email john smith 

을하고 존 스미스의 이메일 주소로 다시 반환합니다.

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

탭 완성 getemail 날 수 있도록 작동 설정 : 그래서 주로 응용 프로그램 내부의 완료를 가능하게 관리했습니다. 그러나 내가 j<tab>을 입력하면 전자 메일 데이터베이스에서 대문자가 올바르게 입력되기 때문에 거부합니다. 어쨌든 이것을 완료하기 위해 배쉬를 얻고 싶습니다. (대문자를 사용하는 경우 J, 작동합니다.)

--complete 옵션을 사용하면 입력을 일치시켜 답장을 변경할 수는 있지만 이상적으로는 명령 줄이 데이터베이스와 일치하는 것이 이상적입니다. 가능한 모든.

readline을 사용할 때 응용 프로그램 내부에서이 작업을 수행했음을 유의하십시오. 이는 문제가되는 bash와의 인터페이스 일뿐입니다.

답변

6

실제로 단어 목록 (-W)에 대해 대소 문자를 구분하지 않으려면 compgen을 수행 할 방법이없는 것처럼 보입니다. 다음 해결 방법을 참조하십시오.

간단한 해결책 : 단어 목록과 입력 토큰을 모두 소문자로 먼저 번역하십시오. 참고 : 인 경우에만을 입력하고 을 입력하면 모든 완료를 모두 소문자로 바꿀 수 있습니다.

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[@]}") 
} 
+0

이 모두 일치하지 않고 단지 첫 번째 일치를 반환으로 위의 솔루션은 완전히 정확하지 않는 것 . "휴식"을 제거하면 해결됩니다. 또 다른 문제점은 nocasematch 옵션이 전혀없는 구형 bash 버전에서는 정상적으로 작동하지 않는다는 것입니다. 그게 최선의 해결책이 될지 모르지만 내 스크립트에서 사용했습니다. 로컬 SHOPT = $ (shopt -p) 로컬 IGNORE_CASE = 0 [[ ""$ {SHOPT # * shopt -u nocasematch} "=="$ SHOPT "]] || IGNORE_CASE = 1 – Neuron

+0

감사합니다, @ Neonon : 모든 일치 항목을 반환하도록 코드를 업데이트했습니다. 'nocasematch' 옵션을 사용할 수 없다면 (당신이 어떤 버전을 도입했는지 아십니까?) : 여러분의 테스트를 사용할 수 있습니다. 옵션이 없으면'tr [: upper :] [: lower :]'기법을 사용한다. 옵션 사용 가능성 테스트를 수행하는 좀 더 간결한 방법은 다음과 같습니다 :'local haveNoCaseMatch = 0 \ n [[-z "$ (shopt -q nocasematch 2> & 1)"]] && haveNoCaseMatch = 1 ' – mklement0

+0

COMPREPLY = ("$ {matches [@]}") 그렇지 않으면 다중 단어 옵션 (예 : 파일 이름)이 깨집니다. – Orwellophile