বাশ স্ক্রিপ্টে একাধিক নির্বাচন মেনু


28

আমি একজন বাশ নবাবী তবে আমি একটি স্ক্রিপ্ট তৈরি করতে চাই যাতে আমি ব্যবহারকারীকে বিকল্পগুলির একটি তালিকা থেকে একাধিক বিকল্প নির্বাচন করার অনুমতি দিতে চাই।

মূলত যা আমি চাই তা নীচের উদাহরণের মতো কিছু:

       #!/bin/bash
       OPTIONS="Hello Quit"
       select opt in $OPTIONS; do
           if [ "$opt" = "Quit" ]; then
            echo done
            exit
           elif [ "$opt" = "Hello" ]; then
            echo Hello World
           else
            clear
            echo bad option
           fi
       done

( Http://www.faqs.org/docs/Linux-HOWTO/Bash-Prog-Intro-HOWTO.html#ss9.1 থেকে উত্সাহিত )

তবে আমার স্ক্রিপ্টে আরও বিকল্প থাকবে এবং আমি বহুগুণ বাছাইয়ের অনুমতি দিতে চাই। সুতরাং এর মতো কিছু:

1) বিকল্প 1
2) বিকল্প 2
3) বিকল্প 3
4) বিকল্প 4
5) সম্পন্ন হয়েছে

তারা যাচাই করেছে তাদের বিষয়ে প্রতিক্রিয়া জানানোও দুর্দান্ত হবে, উদাহরণস্বরূপ প্লাস চিহ্নগুলি যা তারা ইতিমধ্যে নির্বাচন করেছেন next যেমন আপনি যদি "1" নির্বাচন করেন তবে আমি পৃষ্ঠাটি সাফ করতে এবং পুনঃপ্রিন্ট করতে চাই:

1) Option 1 +
2) Option 2
3) Option 3
4) Option 4
5) Done

তারপরে আপনি যদি "3" নির্বাচন করেন:

1) Option 1 +
2) Option 2
3) Option 3 +
4) Option 4
5) Done

এছাড়াও, যদি তারা আবার (1) নির্বাচন করে তবে আমি এটি বিকল্পটি "অনির্বাচিত" করতে চাই:

1) Option 1
2) Option 2
3) Option 3 +
4) Option 4
5) Done

এবং পরিশেষে যখন সম্পন্ন করা হবে তখন আমি প্রোগ্রামগুলির প্রস্থানের আগে প্রদর্শিত হতে নির্বাচিতদের একটি তালিকা চাই, যেমন বর্তমান অবস্থাটি যদি:

1) Option 1
2) Option 2 +
3) Option 3 + 
4) Option 4 +
5) Done

5 টিপে মুদ্রণ করা উচিত:

Option 2, Option 3, Option 4

... এবং স্ক্রিপ্ট সমাপ্ত।

সুতরাং আমার প্রশ্ন - এটি কি ব্যাশে সম্ভব, এবং যদি কেউ কোনও কোডের নমুনা সরবরাহ করতে সক্ষম হয় তবে?

কোন পরামর্শ অনেক প্রশংসা করা হবে।

উত্তর:


35

আমি মনে করি আপনার ডায়লগ বা হুইপটেল একবার দেখে নেওয়া উচিত ।

সংলাপ বাক্স

সম্পাদনা:

আপনার প্রশ্ন থেকে বিকল্পগুলি ব্যবহার করে এখানে একটি উদাহরণ স্ক্রিপ্ট রয়েছে:

#!/bin/bash
cmd=(dialog --separate-output --checklist "Select options:" 22 76 16)
options=(1 "Option 1" off    # any option can be set to default to "on"
         2 "Option 2" off
         3 "Option 3" off
         4 "Option 4" off)
choices=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
clear
for choice in $choices
do
    case $choice in
        1)
            echo "First Option"
            ;;
        2)
            echo "Second Option"
            ;;
        3)
            echo "Third Option"
            ;;
        4)
            echo "Fourth Option"
            ;;
    esac
done

তার জন্য ধন্যবাদ. আমি যতটা আশা করেছিলাম তার চেয়ে জটিল দেখায়, তবে আমি
এটিটি

@ am2605: আমার সম্পাদনা দেখুন। আমি একটি উদাহরণ স্ক্রিপ্ট যুক্ত।
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

3
আপনি এটি একবার বা দু'বার ব্যবহার না করা পর্যন্ত কেবল জটিল দেখায়, তবে আপনি আর কখনও ব্যবহার করবেন না ...
ক্রিস এস

27

যদি আপনি whiptailজটিল মনে করেন , এখানে এটি একটি বাশ-কেবল কোডে যায় যা আপনি যা চান ঠিক তেমন করে । এটি সংক্ষিপ্ত (20 ডলার লাইন), তবে কোনও শিক্ষানবিশের জন্য কিছুটা রহস্যজনক। চেক করা বিকল্পগুলির জন্য "+" দেখানোর পাশাপাশি এটি প্রতিটি ব্যবহারকারীর ক্রিয়া ("অবৈধ বিকল্প", "বিকল্প এক্স পরীক্ষা করা হয়েছিল" / চেক না করা ইত্যাদি) এর জন্য প্রতিক্রিয়াও সরবরাহ করে।

বলেছিল, তুমি সেখানে যাও!

আশা করি আপনি উপভোগ করেছেন ... এটি করা বেশ মজাদার চ্যালেঞ্জ ছিল :)

#!/bin/bash

# customize with your own.
options=("AAA" "BBB" "CCC" "DDD")

menu() {
    echo "Avaliable options:"
    for i in ${!options[@]}; do 
        printf "%3d%s) %s\n" $((i+1)) "${choices[i]:- }" "${options[i]}"
    done
    if [[ "$msg" ]]; then echo "$msg"; fi
}

prompt="Check an option (again to uncheck, ENTER when done): "
while menu && read -rp "$prompt" num && [[ "$num" ]]; do
    [[ "$num" != *[![:digit:]]* ]] &&
    (( num > 0 && num <= ${#options[@]} )) ||
    { msg="Invalid option: $num"; continue; }
    ((num--)); msg="${options[num]} was ${choices[num]:+un}checked"
    [[ "${choices[num]}" ]] && choices[num]="" || choices[num]="+"
done

printf "You selected"; msg=" nothing"
for i in ${!options[@]}; do 
    [[ "${choices[i]}" ]] && { printf " %s" "${options[i]}"; msg=""; }
done
echo "$msg"

ভাল করেছ! ভাল করেছ!
ড্যানিয়েল

4
এটি একটি সামান্য ক্রিপ্টিক তবে আমি আপনার ব্রেস বিস্তৃত বিস্তৃতি এবং গতিশীল অ্যারেগুলির ব্যবহার পছন্দ করি। সবকিছু যেমন ঘটেছিল তেমন পড়তে সক্ষম হতে আমার কিছুটা সময় লেগেছে তবে আমি এটি পছন্দ করি। আপনি প্রিন্টফ () ফাংশনটি অন্তর্নির্মিত ব্যবহার করেছেন তাও আমি পছন্দ করি। আমি এটি সম্পর্কে খুব বেশি জানতে পারি না যে এটি ব্যাশের মধ্যে বিদ্যমান। খুব সহজেই যদি কেউ সি তে কোডিং করতে
অভ্যস্ত হয়

1
যদি কেউ একবারে একাধিক বিকল্প (স্থান পৃথক) নির্বাচন করতে সক্ষম হতে চায়:while menu && read -rp "$prompt" nums && [[ "$nums" ]]; do while read num; do ... done < <(echo $nums |sed "s/ /\n/g") done
ট্যাপসোসিং

1
স্ক্রিপ্টটি বিকাশে এটি সত্যিই দরকারী ছিল যা একাধিক অন্যান্য লোকেরা ব্যবহার করেন যাঁরা উইন্ডেল ব্যবহার করছেন বলে হুইটেল বা অন্যান্য প্যাকেজ অ্যাক্সেস নেই git bash!
আইভল

5

বাহ্যিক নির্ভরতা ছাড়াই কেবল বাশ বৈশিষ্ট্যগুলি ব্যবহার করে আপনি যা করতে চান ঠিক তা করার একটি উপায় এখানে। এটি বর্তমান নির্বাচনগুলি চিহ্নিত করে এবং এগুলিকে টগল করার অনুমতি দেয়।

#!/bin/bash
# Purpose: Demonstrate usage of select and case with toggleable flags to indicate choices
# 2013-05-10 - Dennis Williamson

choice () {
    local choice=$1
    if [[ ${opts[choice]} ]] # toggle
    then
        opts[choice]=
    else
        opts[choice]=+
    fi
}

PS3='Please enter your choice: '
while :
do
    clear
    options=("Option 1 ${opts[1]}" "Option 2 ${opts[2]}" "Option 3 ${opts[3]}" "Done")
    select opt in "${options[@]}"
    do
        case $opt in
            "Option 1 ${opts[1]}")
                choice 1
                break
                ;;
            "Option 2 ${opts[2]}")
                choice 2
                break
                ;;
            "Option 3 ${opts[3]}")
                choice 3
                break
                ;;
            "Option 4 ${opts[4]}")
                choice 4
                break
                ;;
            "Done")
                break 2
                ;;
            *) printf '%s\n' 'invalid option';;
        esac
    done
done

printf '%s\n' 'Options chosen:'
for opt in "${!opts[@]}"
do
    if [[ ${opts[opt]} ]]
    then
        printf '%s\n' "Option $opt"
    fi
done

Ksh এর জন্য, ফাংশনের প্রথম দুটি লাইন পরিবর্তন করুন:

function choice {
    typeset choice=$1

এবং শেবাং থেকে #!/bin/ksh


দারুণ উদাহরণ! কেএসএইচ এটিকে পরিচালনা করতে কীভাবে পরিচালনা করবেন?
FuSsA

1
@ ফুসসা: কেএসএসে এটি কার্যকর করার জন্য প্রয়োজনীয় পরিবর্তনগুলি দেখানোর জন্য আমি আমার উত্তর সম্পাদনা করেছি।
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

1
ব্যাশে অ্যারে হ্যান্ডলিং খুব কঠিন। আপনি কেবল প্রথম নন, পুরো ট্রিনিটিতে আপনি কেবল 40 কের উপরে।
পিটার বলেছেন

1
@ ফুসসা: options=(*)(বা অন্যান্য গ্লোববিং নিদর্শন) আপনাকে অ্যারে ফাইলগুলির একটি তালিকা এনে দেবে। তারপরে চ্যালেঞ্জটি ${opts[@]}হ'ল নির্বাচনের চিহ্নগুলি অ্যারে ( ) এর সাথে একসাথে জিপ করা হবে। এটি একটি forলুপ দিয়ে করা যেতে পারে তবে এটি বাইরের whileলুপের মাধ্যমে প্রতিটি পাসের জন্য চালাতে হবে । আপনি আমার অন্যান্য উত্তরে যেমনটি উল্লেখ করেছেন dialogবা whiptailতেমনিভাবে আপনি ব্যবহার করতে বিবেচনা করতে চাইতে পারেন - যদিও এটি বাহ্যিক নির্ভরতা।
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

1
@ ফুসএসএ: তারপরে আপনি স্ট্রিংটিকে অন্য অ্যারেতে ${opts[@]}সংরক্ষণ করতে পারেন (বা স্ট্রিংটি ব্যবহার এবং সংরক্ষণ করুন, ফাংশনে অতিরিক্ত যুক্তি হিসাবে প্রেরণ করা হয়েছে, পরিবর্তে +)।
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

2

আমি প্রশ্নাবলী নামে একটি গ্রন্থাগার লিখেছি , যা কমান্ড লাইন প্রশ্নাবলী তৈরি করার জন্য একটি মিনি-ডিএসএল। এটি ব্যবহারকারীকে একটি সিরিজের বিভিন্ন প্রশ্নের উত্তর দিতে এবং স্টাডাউটের উত্তরগুলি মুদ্রণের জন্য অনুরোধ করে।

এটি আপনার কাজটি সত্যই সহজ করে তুলেছে। এটি দিয়ে ইনস্টল করুন pip install questionnaireএবং একটি স্ক্রিপ্ট তৈরি করুন, যেমন questions.py:

from questionnaire import Questionnaire
q = Questionnaire(out_type='plain')

q.add_question('options', prompt='Choose some options', prompter='multiple',
               options=['Option 1', 'Option 2', 'Option 3', 'Option 4'], all=None)

q.run()

তারপরে দৌড়াও python questions.py। আপনি স্টাডাউটে মুদ্রিত করা প্রশ্নের উত্তর দেওয়ার কাজ শেষ হয়ে গেলে। এটি পাইথন 2 এবং 3 এর সাথে কাজ করে, এর মধ্যে একটি অবশ্যই আপনার সিস্টেমে প্রায় ইনস্টল করা আছে।

এটি আরও জটিল প্রশ্নাবলীও পরিচালনা করতে পারে, যদি কেউ এটি করতে চায়। এখানে কিছু বৈশিষ্ট্য রয়েছে:

  • স্ট্যান্ডআউটে জেএসএন (বা সরল পাঠ হিসাবে) হিসাবে উত্তরগুলি মুদ্রণ করে
  • ব্যবহারকারীদের ফিরে যেতে এবং প্রশ্নগুলির পুনঃব্যবস্থা করতে অনুমতি দেয়
  • শর্তসাপেক্ষ প্রশ্নগুলি সমর্থন করে (প্রশ্নগুলি পূর্বের উত্তরের উপর নির্ভর করতে পারে)
  • নিম্নলিখিত ধরণের প্রশ্নের জন্য সমর্থন করে: কাঁচা ইনপুট, একটি চয়ন করুন, অনেকগুলি চয়ন করুন
  • প্রশ্ন উপস্থাপনা এবং উত্তর মানগুলির মধ্যে কোনও বাধ্যতামূলক মিলন নেই

1

আমি মস্ত্রেলিওনের উদাহরণটি ব্যবহার করেছি এবং নীচের কোডটি খসড়া করেছি। আপনাকে যা করতে হবে তা হ'ল প্রথম দুটি বিভাগের বিকল্পগুলি এবং ক্রিয়াগুলি আপডেট করা।

#!/bin/bash
#title:         menu.sh
#description:   Menu which allows multiple items to be selected
#author:        Nathan Davieau
#               Based on script from MestreLion
#created:       May 19 2016
#updated:       N/A
#version:       1.0
#usage:         ./menu.sh
#==============================================================================

#Menu options
options[0]="AAA"
options[1]="BBB"
options[2]="CCC"
options[3]="DDD"
options[4]="EEE"

#Actions to take based on selection
function ACTIONS {
    if [[ ${choices[0]} ]]; then
        #Option 1 selected
        echo "Option 1 selected"
    fi
    if [[ ${choices[1]} ]]; then
        #Option 2 selected
        echo "Option 2 selected"
    fi
    if [[ ${choices[2]} ]]; then
        #Option 3 selected
        echo "Option 3 selected"
    fi
    if [[ ${choices[3]} ]]; then
        #Option 4 selected
        echo "Option 4 selected"
    fi
    if [[ ${choices[4]} ]]; then
        #Option 5 selected
        echo "Option 5 selected"
    fi
}

#Variables
ERROR=" "

#Clear screen for menu
clear

#Menu function
function MENU {
    echo "Menu Options"
    for NUM in ${!options[@]}; do
        echo "[""${choices[NUM]:- }""]" $(( NUM+1 ))") ${options[NUM]}"
    done
    echo "$ERROR"
}

#Menu loop
while MENU && read -e -p "Select the desired options using their number (again to uncheck, ENTER when done): " -n1 SELECTION && [[ -n "$SELECTION" ]]; do
    clear
    if [[ "$SELECTION" == *[[:digit:]]* && $SELECTION -ge 1 && $SELECTION -le ${#options[@]} ]]; then
        (( SELECTION-- ))
        if [[ "${choices[SELECTION]}" == "+" ]]; then
            choices[SELECTION]=""
        else
            choices[SELECTION]="+"
        fi
            ERROR=" "
    else
        ERROR="Invalid option: $SELECTION"
    fi
done

ACTIONS

দুর্দান্ত উত্তর। সংখ্যা বাড়ানোর জন্য একটি নোট যুক্ত করুন, ই..জি বিকল্প 15; n1 SELECTIONঅঙ্কের সংখ্যা বাড়ানোর জন্য গুরুত্বপূর্ণ অংশটি কোথায় ..
ডিবিএফ

যুক্ত করতে ভুলে গেছি; যেখানে -n2 SELECTIONদুটি অঙ্ক গ্রহণ করা হবে (উদাঃ 15), -n3তিনটি গ্রহণ করবে (উদাঃ 153), ইত্যাদি
Dbf

1

এখানে একটি বাশ ফাংশন যা ব্যবহারকারীকে তীর কী এবং স্পেস সহ একাধিক বিকল্প নির্বাচন করতে এবং এন্টার দিয়ে নিশ্চিত করার অনুমতি দেয়। এটিতে মেনুর মতো সুন্দর লাগছে। আমি এটি /unix//a/415155 এর সহায়তায় লিখেছি । এটিকে এভাবে বলা যেতে পারে:

multiselect result "Option 1;Option 2;Option 3" "true;;true"

ফলাফলটি প্রথম আর্গুমেন্ট হিসাবে সরবরাহ করা নামের সাথে একটি ভেরিয়েবলের অ্যারে হিসাবে সংরক্ষণ করা হয়। শেষ যুক্তি alচ্ছিক এবং ডিফল্টরূপে নির্বাচিত কিছু বিকল্প তৈরির জন্য ব্যবহৃত হয়। দেখে মনে হচ্ছে।

function prompt_for_multiselect {

    # little helpers for terminal print control and key input
    ESC=$( printf "\033")
    cursor_blink_on()   { printf "$ESC[?25h"; }
    cursor_blink_off()  { printf "$ESC[?25l"; }
    cursor_to()         { printf "$ESC[$1;${2:-1}H"; }
    print_inactive()    { printf "$2   $1 "; }
    print_active()      { printf "$2  $ESC[7m $1 $ESC[27m"; }
    get_cursor_row()    { IFS=';' read -sdR -p $'\E[6n' ROW COL; echo ${ROW#*[}; }
    key_input()         {
      local key
      IFS= read -rsn1 key 2>/dev/null >&2
      if [[ $key = ""      ]]; then echo enter; fi;
      if [[ $key = $'\x20' ]]; then echo space; fi;
      if [[ $key = $'\x1b' ]]; then
        read -rsn2 key
        if [[ $key = [A ]]; then echo up;    fi;
        if [[ $key = [B ]]; then echo down;  fi;
      fi 
    }
    toggle_option()    {
      local arr_name=$1
      eval "local arr=(\"\${${arr_name}[@]}\")"
      local option=$2
      if [[ ${arr[option]} == true ]]; then
        arr[option]=
      else
        arr[option]=true
      fi
      eval $arr_name='("${arr[@]}")'
    }

    local retval=$1
    local options
    local defaults

    IFS=';' read -r -a options <<< "$2"
    if [[ -z $3 ]]; then
      defaults=()
    else
      IFS=';' read -r -a defaults <<< "$3"
    fi
    local selected=()

    for ((i=0; i<${#options[@]}; i++)); do
      selected+=("${defaults[i]}")
      printf "\n"
    done

    # determine current screen position for overwriting the options
    local lastrow=`get_cursor_row`
    local startrow=$(($lastrow - ${#options[@]}))

    # ensure cursor and input echoing back on upon a ctrl+c during read -s
    trap "cursor_blink_on; stty echo; printf '\n'; exit" 2
    cursor_blink_off

    local active=0
    while true; do
        # print options by overwriting the last lines
        local idx=0
        for option in "${options[@]}"; do
            local prefix="[ ]"
            if [[ ${selected[idx]} == true ]]; then
              prefix="[x]"
            fi

            cursor_to $(($startrow + $idx))
            if [ $idx -eq $active ]; then
                print_active "$option" "$prefix"
            else
                print_inactive "$option" "$prefix"
            fi
            ((idx++))
        done

        # user key control
        case `key_input` in
            space)  toggle_option selected $active;;
            enter)  break;;
            up)     ((active--));
                    if [ $active -lt 0 ]; then active=$((${#options[@]} - 1)); fi;;
            down)   ((active++));
                    if [ $active -ge ${#options[@]} ]; then active=0; fi;;
        esac
    done

    # cursor position back to normal
    cursor_to $lastrow
    printf "\n"
    cursor_blink_on

    eval $retval='("${selected[@]}")'
}

আপনি কিভাবে এটি কল? ফাইলটি দেখতে কেমন হবে?
এলি

1

যেহেতু আমি প্রম্পট-টুলকিট (পাইথন), ডায়ালগুয়ার (মরিচা) বা অনুসন্ধানকারী (নোড) এর জন্য কোনও উপযুক্ত BASH অল্টারনেটিভ খুঁজে পাইনি আমি নিজেই এটি চেষ্টা করে দেখেছি:

https://i.stack.imgur.com/6AyAI.png

https://asciinema.org/a/Y4hLxnN20JtAlrn3hsC6dCRn8 https://gist.github.com/blurayne/f63c5a8521c0eeab8e9afd8baa45c65e


-1
export supermode=none

source easybashgui

list "Option 1" "Option 2" "Option 3" "Option 4"

2
এটি আপনি কী করছেন তার একটি বিবরণ যুক্ত করতে পারেন? ভবিষ্যতের দর্শকদের জন্য, ওপি-তে তেমন কিছু নয়।
এসএমএল

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.