2012-05-18 13 views
12

निम्नलिखित बैश समापन संभव शब्दों (यानी पूर्णता) की एक सरणी compgen करने के लिए गुजरता है।बैश स्वत: पूर्णता - इस सरणी को बिना किसी महत्वपूर्ण व्हाइटस्पेस के संकलन के कंपेन में कैसे पास किया जाए?

basenames=("foo" "fu bar" "baz"); 

COMPREPLY=($(compgen -W "${basenames[*]}" -- "${COMP_WORDS[COMP_CWORD]}")) 

समस्या यह है कि है "foo बार" शब्द बंटवारे के लिए तत्वों धन्यवाद करने के लिए माना जाता है, कि सरणी तत्वों में खाली स्थान के संरक्षित नहीं किया जाता है। क्या व्हाइटस्पेस को संरक्षित करने का कोई तरीका है, ताकि 3 तत्व दिखाए जाएं, और 4 नहीं?

संपादित

basenames, फ़ाइल नाम होता है, जो लगभग हर चरित्र है (से अलग/और \ 0) की अनुमति दी है।

संपादित 2

डब्ल्यू झंडा एक शब्द भी उम्मीद है, कि foo bar foobar की तरह कुछ है। इसमें कई तत्वों को पास करना (यह ${basenames[@]} करेगा) काम नहीं करेगा।

संपादित 3

बदल दिया examplary basenames सरणी (ताकि foo और foo bar से foo ढह नहीं हो जाएगा)।

एक नई पंक्ति का उपयोग करते हुए शब्द को अलग करने के काम करता है:

local IFS=$'\n' 
COMPREPLY=($(compgen -W "$(printf "%s\n" "${basenames[@]}")" -- ${COMP_WORDS[COMP_CWORD]}")) 

\0 का प्रयोग नहीं करता है:

local IFS=$'\0' 
COMPREPLY=($(compgen -W "$(printf "%s\0" "${basenames[@]}")" -- ${COMP_WORDS[COMP_CWORD]}")) 

उत्तर

8

क्यों compgen से परेशान? बस उन्हें मैन्युअल रूप से COMPREPLY में जोड़ें। निम्नलिखित फ़ाइल नामों को सुरक्षित रूप से संभालने, /some/path से मेल खाने वाले फ़ाइल नामों को पूरा करेगा।

some_completion_function() { 
    local files=("/some/path/$2"*) 
    [[ -e ${files[0]} ]] && COMPREPLY=("${files[@]##*/}") 
} 

compgen सुरक्षित रूप से फ़ाइल नामों को संभालना संभव नहीं है।

+0

+1 इस प्रकार मैंने वास्तव में जो हासिल किया था वह हासिल किया। वास्तव में अच्छी सलाह! – helpermethod

+0

"$ 2" और "## * /" क्या हैं? – oluc

+0

## */आखिरी '/' तक सिर हटा देता है; $ 2 वर्तमान समापन शब्द है; सही? – oluc

-2

आप लगभग हमेशा एक संकेत पर एक तारक के बजाय एक सरणी सब्स्क्रिप्ट का उपयोग करना चाहिए ।

COMPREPLY=($(compgen -W "${basenames[@]}" -- "${COMP_WORDS[COMP_CWORD]}")) 
man bash से

(या देखने Bash Reference Manual):

तो सबस्क्रिप्ट @ या * है, शब्द नाम के सभी सदस्यों को विस्तृत करता है। ये सबस्क्रिप्ट तभी भिन्न होती है जब शब्द डबल कोट्स के भीतर प्रकट होता है। यदि शब्द डबल-उद्धृत है, ${name[*]} आईएफएस विशेष चर के पहले अक्षर से अलग प्रत्येक सरणी सदस्य के मूल्य के साथ एक शब्द तक फैला है, और ${name[@]} नाम के प्रत्येक तत्व को एक अलग शब्द में फैलाता है।

दूसरे शब्दों में, हस्ताक्षर फॉर्म सरणी "flattens" पर है। तारांकन फार्म इसे संरक्षित करता है।

+4

यदि मैं * को @ के साथ प्रतिस्थापित करता हूं, तो ऑटो पूर्णता पूरी तरह से काम करना बंद कर देती है। – helpermethod

+7

'compgen -W' की आवश्यकता है कि सभी समापन एक "शब्द" में प्रदान किए जाएं, जो' [@] 'नहीं करता है। [पिछले प्रश्न का मेरा उत्तर] देखें (http://stackoverflow.com/questions/3348443/a-confusion-about-array-versus-array-in-the-context-of-a-bash-comple/3355375# 3355375) एक विस्तृत स्पष्टीकरण के लिए। –

+11

-1: यह सलाह संदर्भ से बाहर है कि यह सिर्फ सादा गलत है। '-W' एक * एकल तर्क * की अपेक्षा करता है और' @ 'का उपयोग करके आपको उनमें से एक अनिर्धारित संख्या मिल जाएगी। – antak

1

शायद यह कर सकता:

COMPREPLY=($(compgen -W "$(printf "%q " "${basenames[*]}")" -- "${COMP_WORDS[COMP_CWORD]}")) 
+0

'*' के साथ नहीं, लेकिन '@' के साथ यह काम करता प्रतीत होता है। –

+0

यह लगभग काम करता है, लेकिन यह "फू बार" को 2 तत्वों के रूप में मानता है, जबकि मैं इसे एक तत्व के रूप में प्रदर्शित करना चाहता हूं। – helpermethod

+0

@ ओलिवर वेइलर: क्या आपने ग्लेन को '@' के साथ प्रयोग किया था? –

संबंधित मुद्दे