Bash tricks: Difference between revisions

From wikinotes
 
Line 32: Line 32:


<source lang="bash">
<source lang="bash">
options=(
# Format:  ${MENU_ITEM} ${COMMAND} ...
     "1- this"
CHOICES=(
    "2- is"
     "say hi"
     "3- a"
        "echo hi && sleep 1"
    "4- test"
 
     "say bye"
        "echo bye && sleep 1"
)
)




executeMenu() {
print_error() {
     # substitute with command to execute for each menu
     # """ prints an error with a sleep
     echo "ENTERING MENU $1"
    # """
    message="$1"
    echo
    echo
    echo $message
    sleep 2
}
 
 
show_menu() {
    # """ prints menu w/ choices
    # """
     clear
    echo "Choose Desktop:"
    for ((i=1; i<=${#CHOICES[@]}; i+=2)); do
        local index="$(expr $i / 2)"
        local name="${CHOICES[$i]}"
        echo "   ${index}) ${name}"  
    done
}
}




selectionMenu() {
choose_menu_index() {
     #create array from argument
     # """ requests an integer with the menu choice you'd like to load
     menu=("${@}")
     # """
    local num_choices="$(expr $(expr ${#CHOICES[@]} / 2) - 1)"
    echo
    echo -n "Press (0-${num_choices} [default:0]): " && read index
 
    # defaults to 0
    test -z "$index" && index=0
 
    # must be integer
    if ! [ "$index" -eq "$index" ] 2> /dev/null ; then
        print_error "Expected Integer. Received: ${index}"
        return 1
    fi


     #ensure argument is present
     # reject numbers above $num_choices
     if [ "${menu[0]}" == "" ] ; then
     if test "$index" -gt "$num_choices" ; then
         echo "Error: selectionMenu() requires an array as an argument"
         print_error "Expected Integer <${num_choices}. Received: ${index}"
         exit 0
         return 1
     fi
     fi


     # variables
     # exec chosen menu, after newline
     local menuSize=$(echo ${#menu[@]} - 1 | bc -l) # size of menu array
     local array_index=$((2*$(expr $index + 1)))
    local selLine=0                                # selected Menu Line
 
     selBttn=""                                     # button pushed from menu
     eval "${CHOICES[$array_index]}"
    initMenu=1                                      # first run of current menu=true
}


    printMenu() {
        clear
        case $selBttn in
            q)
                quit=1
                exit 0
                ;;
            k|p)
                ((selLine--))
                ;;
            j|n)
                ((selLine++))
                ;;
            '' )
                #otherwise menu is entered on first load
                if [ "$initMenu" != "1" ] ; then
                    initMenu=1
                    executeMenu "$selLine"
                fi
                ;;
        esac
        initMenu=0
   
        #restrict menu selection to available menu options
        if [ "$selLine" -gt "$menuSize" ] ; then
            selLine=$menuSize
        elif [ "$selLine" -lt "0" ] ; then
            selLine=0
        fi


        #print menu to screen
mainloop() {
        for i in $( seq 0 $menuSize ) ; do
    if [[ $(tty) == /dev/tty1 ]] ; then
            if [ "$selLine" == "$i" ] ; then
        while true; do
                echo "* ${menu[$i]}"
             show_menu
             else
             choose_menu_index
                echo "  ${menu[$i]}"
             fi
         done
         done
        #read single char input
        read -n 1 selBttn
        printMenu
    }
    if [ "$quit" != "1" ] ; then
        printMenu
     fi
     fi
}  
}
 
selectionMenu "${options[@]}"
</source>
</source>
</blockquote><!-- simple menu -->
</blockquote><!-- simple menu -->

Revision as of 11:55, 17 July 2021

raw output

Sometimes when parsing shell output, it is useful to see the actual raw output before colours/escape sequences are applied in order to diagnose issues. In this instance, you can pipe a command to cat.

( ls -l  ;  ls -l --color=always  ) | cat -vet

total 41624$
drwxr-xr-x 2 will will     4096 Dec  2 08:01 new$
-rw-r--r-- 1 will will 42557440 Dec  2 08:01 old.tar$
total 41624$
drwxr-xr-x 2 will will     4096 Dec  2 08:01 ^[[01;34mnew^[[0m$
-rw-r--r-- 1 will will 42557440 Dec  2 08:01 old.tar$

Find the Number of tokens in a line:

VAR='some/string/with words'
echo $VAR | tr -cd  "/" | wc -c

Simple Menu

Consider using ncurses or dialog instead before implementing your own menu.
The following should also work.

# Format:  ${MENU_ITEM} ${COMMAND} ...
CHOICES=(
    "say hi"
        "echo hi && sleep 1"

    "say bye"
        "echo bye && sleep 1"
)


print_error() {
    # """ prints an error with a sleep
    # """
    message="$1"
    echo
    echo
    echo $message
    sleep 2
}


show_menu() {
    # """ prints menu w/ choices
    # """
    clear
    echo "Choose Desktop:"
    for ((i=1; i<=${#CHOICES[@]}; i+=2)); do
        local index="$(expr $i / 2)"
        local name="${CHOICES[$i]}"
        echo "    ${index}) ${name}" 
    done
}


choose_menu_index() {
    # """ requests an integer with the menu choice you'd like to load
    # """
    local num_choices="$(expr $(expr ${#CHOICES[@]} / 2) - 1)"
    echo
    echo -n "Press (0-${num_choices} [default:0]): " && read index

    # defaults to 0
    test -z "$index" && index=0

    # must be integer
    if ! [ "$index" -eq "$index" ] 2> /dev/null ; then
        print_error "Expected Integer. Received: ${index}"
        return 1
    fi

    # reject numbers above $num_choices
    if test "$index" -gt "$num_choices" ; then
        print_error "Expected Integer <${num_choices}. Received: ${index}"
        return 1
    fi

    # exec chosen menu, after newline
    local array_index=$((2*$(expr $index + 1)))

    eval "${CHOICES[$array_index]}"
}


mainloop() {
    if [[ $(tty) == /dev/tty1 ]] ; then
        while true; do
            show_menu
            choose_menu_index
        done
    fi
}