7745 次
5 に答える
8
このあまり洗練されていない後処理ソリューションは、私にはうまくいくようです (GNU bash、バージョン 3.1.17(6)-release (i686-pc-cygwin))。(いつものようにボーダーケースをテストしなかった場合を除きます:))
物事を評価する必要はありません。引用符には2種類しかありません。
compgen はスペースをエスケープしたくないので、自分でスペースをエスケープします (単語が引用符で始まっていない場合のみ)。これには、エスケープされた値を持つ完全なリスト (ダブルタブ) の副作用もあります。ls はそれをしないので、それが良いかどうかはわかりません...
編集:単語内の単一および二重のクォートを処理するように修正されました。基本的に、3 つのアンエスケープを渡す必要があります :)。1 番目は grep の場合、2 番目は compgen の場合、最後は words コマンド自体の場合です。
_find_words()
{
search=$(eval echo "$cur" 2>/dev/null || eval echo "$cur'" 2>/dev/null || eval echo "$cur\"" 2>/dev/null || "")
grep -- "^$search" words.dat | sed -e "{" -e 's#\\#\\\\#g' -e "s#'#\\\'#g" -e 's#"#\\\"#g' -e "}"
}
_words_complete()
{
local IFS=$'\n'
COMPREPLY=()
local cur="${COMP_WORDS[COMP_CWORD]}"
COMPREPLY=( $( compgen -W "$(_find_words)" -- "$cur" ) )
local escaped_single_qoute="'\''"
local i=0
for entry in ${COMPREPLY[*]}
do
if [[ "${cur:0:1}" == "'" ]]
then
# started with single quote, escaping only other single quotes
# [']bla'bla"bla\bla bla --> [']bla'\''bla"bla\bla bla
COMPREPLY[$i]="${entry//\'/${escaped_single_qoute}}"
elif [[ "${cur:0:1}" == "\"" ]]
then
# started with double quote, escaping all double quotes and all backslashes
# ["]bla'bla"bla\bla bla --> ["]bla'bla\"bla\\bla bla
entry="${entry//\\/\\\\}"
COMPREPLY[$i]="${entry//\"/\\\"}"
else
# no quotes in front, escaping _everything_
# [ ]bla'bla"bla\bla bla --> [ ]bla\'bla\"bla\\bla\ bla
entry="${entry//\\/\\\\}"
entry="${entry//\'/\'}"
entry="${entry//\"/\\\"}"
COMPREPLY[$i]="${entry// /\\ }"
fi
(( i++ ))
done
}
于 2009-07-18T04:22:43.060 に答える
5
_foo ()
{
words="bar one"$'\n'"bar two"
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
prev=${COMP_WORDS[COMP_CWORD-1]}
cur=${cur//\./\\\.}
local IFS=$'\n'
COMPREPLY=( $( grep -i "^$cur" <( echo "$words" ) | sed -e 's/ /\\ /g' ) )
return 0
}
complete -o bashdefault -o default -o nospace -F _foo words
于 2013-12-13T16:46:32.723 に答える
1
パイプ_find_words
スルーsed
し、各行を引用符で囲みます。"
また、コマンド ラインを入力するときは、タブ補完する単語の前にまたはを必ず入力して'
ください。そうしないと、この方法は機能しません。
_find_words() { cat words.dat; }
_words_complete()
{
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
local IFS=$'\n'
COMPREPLY=( $( compgen -W "$( _find_words | sed 's/^/\x27/; s/$/\x27/' )" \
-- "$cur" ) )
}
complete -F _words_complete words
コマンドライン:
$ words "ba░
tab
$ words "bar ░
tabtab
bar one bar two
$ words "bar o░
tab
$ words "bar one" ░
于 2015-07-17T15:40:02.903 に答える