कॉमा-अलग-अलग मूल्यों के लिए बैश पूरा होना


16

मैं अल्पविराम से अलग पैरामीटर सूची के लिए पूर्ण नियम बनाना चाहूंगा। जैसे मेरे पास कमांड है जो सर्वर नामों की सूची प्राप्त करता है:

myscript -s name1,name2,name3

इस समय मैं निम्नलिखित पूरा करने में कामयाब रहा:

_myscript () {
  local cur prev opts

  _get_comp_words_by_ref cur prev

  opts='-s'

  servers='name1 name2 name3'

  if [[ ${cur} == -* ]] ; then
    COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
  else
    case "${prev}" in
      -s)
        if [[ "$cur" == *,* ]]; then
          local realcur prefix
          realcur=${cur##*,}
          prefix=${cur%,*}
          COMPREPLY=( $(compgen -W "${servers}" -P "${prefix}," -- ${realcur}) )
        else
          COMPREPLY=( $(compgen -W "${servers}" -- ${cur}) )
        fi
        ;;
      *)
        # do nothing
        ;;
    esac
  fi
}

लेकिन इसमें कम से कम 2 समस्याएं हैं:

  1. वर्तमान मूल्य के सुझावों में उनके उपसर्ग के सभी पिछले मूल्य शामिल हैं।
  2. यह डुप्लिकेट मानों पर विचार नहीं करता है।

ऐसे मामलों के लिए सबसे अच्छा अभ्यास क्या है? हो सकता है कि बैश-पूर्ति में csv-सूचियों के लिए कुछ बंडल कार्य हों?


3
क्या मदद कर सकता है कि आप अल्पविराम से अलग किए गए मानों को एक पुनरावृत्त सूची में इस तरह विभाजित कर सकते हैं: IFS=, LIST=("$VARIABLE")जहां $ VARIABLE में आपके अल्पविराम द्वारा अलग किए गए मान शामिल हैं।
माइकल एहरेनरिच

2
अच्छा विचार @MichaelEhrenreich, लेकिन आप बोली नहीं होना चाहिए $VARIABLE, नहीं तो शब्द को तोड़ने नहीं होता है। बस उपयोग करें IFS=, LIST=($VARIABLE)
Guss

जवाबों:


6

मूल रूप से आपके द्वारा बताई गई समस्याओं को ठीक करने का कोई तरीका नहीं है, क्योंकि बैश COMPREPLYसीधे डिस्प्ले में मानों का उपयोग करता है और फिर उपयोगकर्ता के पाठ को बदलने के लिए - जबकि आप जो चाहते हैं उसे प्राप्त करने के लिए, आपको पहले संभव पूर्णताएं उत्पन्न करने की आवश्यकता होगी (बस अतिरिक्त सर्वर नाम, उपसर्ग के बिना) बैश के लिए प्रदर्शित करने के लिए, तब जब बैश सबसे लंबे समय तक गैर-विरोधी स्ट्रिंग के साथ उपयोगकर्ता पाठ को बदलने के लिए है, तो आपको उपसर्ग के साथ पाठ उत्पन्न करने के लिए अपनी स्क्रिप्ट को फिर से कॉल करने की आवश्यकता होगी - और बैश उसके लिए कोई सुविधा नहीं है।

सबसे अच्छा जो मैं साथ आ सकता था, वह यह है कि COMPREPLYपूरे उपसर्ग ( COMPREPLY=( "${prefix},"$(compgen -W "${servers[@]}" -- ${realcur}) )) वाले पहले शब्द के साथ ही उत्पन्न किया जाए, ताकि यदि केवल एक ही संभव पूरा हो, तो यह स्वचालित रूप से सही ढंग से पूरा हो जाता है, जबकि अगर एक से अधिक संभावित पूर्णता है , फिर बैश को हटा दिया जाएगा जो अब तक टाइप नहीं किया गया था (क्योंकि पहले शब्द में COMPREPLYपूरे उपसर्ग है और इस प्रकार वर्तमान में टाइप किए गए पाठ से मेल खाता है और उपयोगकर्ता के पाठ को बदलने के लिए बैश द्वारा चुना जाएगा) और उपसर्ग के बिना विकल्पों को प्रदर्शित करेगा - सिवाय उस एक शब्द के लिए जिसमें पहले से ही उपसर्ग है, इसलिए आउटपुट इस तरह दिखेगा:

$ command -s banana,a
ananas     apricot    banana,apple

"सेब" को पूरा होने वाले विकल्पों में अंतिम रूप दिया जाता है क्योंकि यह उपसर्ग करता है जो "बी" से शुरू होता है - बहुत भ्रामक। इसलिए मैं ऐसा करने की सलाह नहीं देता।

डुप्लिकेट के बारे में - डुप्लिकेट नहीं दिखाने के लिए, आपको बस $prefixइसके भाग (आसान IFS="," prefix_parts=($prefix):) में तोड़ने की जरूरत है और फिर उन पर पुनरावृत्ति करें और केवल उन $serversनामों को छोड़ दें जो पहले से सूचीबद्ध नहीं हैं। टाइप करने के लिए इसकी थकाऊ, इसलिए मैं इसे यहां नहीं दिखाऊंगा, लेकिन अपेक्षाकृत तुच्छ इसलिए मुझे यकीन है कि आप :-) का प्रबंधन कर सकते हैं।

संक्षेप में, मुझे नहीं लगता कि आपको इनपुट विकल्पों के लिए अल्पविराम से अलग किए गए मानों का उपयोग करना चाहिए, कम से कम यदि आप उम्मीद करते हैं कि आप पूरा होने में मदद करेंगे।

आप एक विकल्प प्रारूप का समर्थन कर सकते हैं जो इस तरह है: command -s <server> [<server> [..]]और फिर -sविकल्प के तुरंत बाद एक के अलावा अन्य प्रविष्टियों को पूरा करने के लिए , बस $COMP_WORDSसरणी से वापस स्कैन करें $COMP_CWORDजब तक कि आपको एक विकल्प नहीं मिल जाता है (स्ट्रिंग जो मेल खाती है -*) और यदि "-s" तब आपको सर्वर नाम पूरा करने की आवश्यकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.