stevendesu stevendesu - 3 months ago 6
Bash Question

Colored text printing spaces in shell script

I wish to create a shell script to output my current memory usage and CPU usage as bars (for use in a tmux config file)

The expected output will be something like this:

desired output of my load.sh script

My shell script so far looks like this:

# Determine CPU load
pcpu=$(ps -Ao pcpu | awk '{sum = sum + $1}END{print sum}')

# Determine MEM load
mem=$(ps -Ao rss | awk '{sum = sum + $1}END{print sum}')

# Determine total MEM
tmem=$(cat /proc/info | awk '/MemTotal/ {print $2}')

# Helper function to convert KB to KB/MB/GB/TB
pretty_print() {
# We start with KB from /proc/meminfo and ps
[ $1 -lt 16384 ] && echo "${KB} K" && return
MB=$((($1+512)/1024))
[ $MB -lt 16384 ] && echo "${KB} M" && return
GB=$((($MG+512)/1024))
[ $GB -lt 16384 ] && echo "${KB} G" && return
TB=$((($GB+512)/1024))
[ $TB -lt 16384 ] && echo "${KB} T" && return
}

# Helper function to print bars for percentages
print_bars() {
local GREEN='\033[32m'
local YELLOW='\033[33m'
local RED='\033[31m'
local RESET='\033[0m'
local current=$(($1*10/$2))
local bars=0
while [ $current -gt 0 ]; do
[ $bars -lt 3 ] && echo $GREEN
[ $bars -gt 2 ] && echo $YELLOW
[ $bars -gt 5 ] && echo $RED
echo '|'
current=$(($current - 1))
bars=$((bars + 1))
done
echo $RESET
while [ $bars -lt 10 ]; do
echo ' '
bars=$((bars + 1))
done
}

# Output: CPU $pcpu [||| ] - MEM $mem / $tmem [||| ]
echo CPU $pcpu \[$(print_bars $pcpu 100)\] - MEM $(human_print $mem) / $(human_print $tmem) \[$(print_bars $mem $tmem)\]


I'm encountering two separate issues:


  1. All terminating spaces are stripped from the output of
    print_bars
    . This is causing it to print things like
    [| ]
    or
    [|||| ]
    instead of the appropriate
    [| ]
    and
    [|||| ]

  2. The more annoying and the reason for this post: the color codes (
    \033[Xm
    ) are being printed as spaces in my terminal, putting spaces between the bars like so:



enter image description here

Answer

You need to put double quotes around the calls to print_bars to prevent word splitting, which removes excess spaces.

echo "CPU $pcpu [$(print_bars $pcpu 100)] - MEM $(human_print $mem) / $(human_print $tmem) [$(print_bars $mem $tmem)]"

The spaces around the color codes are because commands like

echo $GREEN

add a newline after the output, which turns into a space by word splitting. You should use

echo -n $GREEN

or

printf "%s" "$GREEN"
Comments