Bash - changing a color of a substring

Hello!

I need to write a bash script for my university classes, and I came up with an idea of a program that would test the speed of typing - there is some random text that you have to rewrite, and the script measures time, number of mistakes etc. The text would be visible on the screen all the time, and I would like to dynamically refresh it and change the color of correctly written characters to green (or to red - for those which are wrong). This would require some way of manipulating a color of a single character in a string - is something like that even possible?

I was thinking about something like inserting $(tput setaf 1)/some_character/$(tput sgr0)" on a specified position of a string - let's say I have a string "abcd", and I want one of the characters (for example, the one on the position 2 - in this case it would be c) to be green. Can something like that be done?

I will be very grateful for any suggestions.
PS. Sorry for my English, if there are any mistakes.

Unless 'tput' is a shell built-in (it's not in my environment), I'd avoid it as that's an awful lot of process creation. I'd use escape sequences assuming you're working in an xterm environment. This works under xterm run by either Kshell or bash and should illustrate how to change colours using escape sequences:

#!/usr/bin/env ksh
grey=30
red=31
green=32
yellow=33
blue=34
purple=35
white=36

function colour_string
{
        typeset colour=$1
        shift
        printf  "\e[1;%dm%s" $colour "$*"   set the desired colour with escape, then write string
}

echo "type these characters without spaces:"
desired=( a b c d e f g)
echo "${desired[@]}"
i=0
while read -n 1 x
do
        resp[$i]=$x
        i=$(( i + 1 ))
        if (( i >= ${#desired[@]} ))
        then
                break;
        fi
done

printf "\n"
for (( i = 0; i < ${#desired[@]}; i++ ))
do
        if [[ ${resp[$i]} == ${desired[$i]} ]]
        then
                colour_string $green "${resp[$i]}"
        else
                colour_string $red "${resp[$i]}"
        fi
done
printf "\n"

Or for example, just put the sequences in variables and use those in the format part of printf.

$ BLUE="\e[0;34m"
$ GREEN="\e[0;32m"
$ RED="\e[0;31m"
$ NOCOLOR="\e[0m"
$ printf "%s $BLUE%s $RED%s $GREEN%s $NOCOLOR\n" HELLO BLUE RED GREEN
HELLO BLUE RED GREEN

ANSI escape sequences:

1 Like

Thanks a lot, the ANSI escape sequences list was exactly what I needed, I didn't know about that until now.