Bash tricks: Difference between revisions

From wikinotes
No edit summary
Line 25: Line 25:
</syntaxhighlight>
</syntaxhighlight>
</blockquote><!-- num tokens in a line -->
</blockquote><!-- num tokens in a line -->
= Repeat character N times =
<blockquote>
<syntaxhighlight lang="bash">
printf -- '=%.0s' {1..5}          # repeat '=' 5 times
printf -- '=%.0s' {1..${#header}}  # repeat '=' for each char in $header
</syntaxhighlight>
</blockquote><!-- repeat character n times -->


= Iterate over tokenize string =
= Iterate over tokenize string =

Revision as of 16:28, 25 December 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

Repeat character N times

printf -- '=%.0s' {1..5}           # repeat '=' 5 times
printf -- '=%.0s' {1..${#header}}  # repeat '=' for each char in $header

Iterate over tokenize string

Useful for iterating over $PATH style variable paths that may contain spaces.

echo "$PATH" | tr ':' '\n' | while read -r path; do
    echo "--$path"
done

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
}