0

So, I was trying to create an aesthetic horizontally scrolling text in the console using bash. I wasn't sure how to go about this. here's an example:

Original string: Hi! How are you doing on this fine evening?

1st loop:
Hi! H
2nd:
i! Ho
3rd:
! How
4th:
 How 

and so on. How would I go about this? I would preferably have it delete the last printed loop so it is a smooth scrolling string. Any help would be appreciated! Thanks! (Also feel free to ask questions, this description was kinda bad :P)

1
  • Printing a raw \r is probably your friend here. What have you already tried?
    – kingsfoil
    Commented Oct 22, 2022 at 3:11

3 Answers 3

1

This one is a bit hacky, but I believe it's the effect you are describing. In the output each of these lines will overwrite the previous entry so that it produces something like the old <marquee> tags, but in the terminal.

Hello There!
ello There! He
o There! Hello
There! Hello
ere! Hello The
e! Hello There
Hello There!
ello There! He
lo There! Hell
There! Hello
here! Hello Th
re! Hello Ther
! Hello There!
Hello There! H
llo There! Hel
o There! Hello
There! Hello T
here! Hello Th
e! Hello There
Hello There!
#!/bin/bash

function slice_loop () { ## grab a slice of a string, and if you go past the end loop back around
    local str="$1"
    local start=$2
    local how_many=$3
    local len=${#str};

    local result="";

    for ((i=0; i < how_many; i++))
    do
        local index=$(((start+i) % len)) ## Grab the index of the needed char (wrapping around if need be)
        local char="${str:index:1}" ## Select the character at that index
        local result="$result$char" ## Append to result
    done

    echo -n $result
}

msg="Hello There! ";
begin=0

while :
do
    slice=$(slice_loop "$msg" $begin 14);
    echo -ne "\r";
    echo -n $slice;
    echo -ne "              \r";
    sleep 0.08;
    ((begin=begin+1));
done

Save that in a file and run it and you should see the string "Hello There!" scroll past. It's a bit jittery but you can tweak that to make it a bit neater.

1

As the other said you should use echo or printf with carriage return \r.

So what you want is to print only 5 chars per loop you could use the script below for that behavior:

#!/bin/bash

null=$'\0'
text="Hi! How are you doing on this fine evening? ${null}"

#while :; do
count=0
for (( i = 0; i < "${#text}"; i++ )); do
   printf "\r%s" "${text:$i:5}"
   sleep 0.3
done
#done
echo

With this line printf "\r%s" "${text:$i:5}" I'm printing 5 characters per loop, where the $i is the current index and the 5 is the length of the string to print.
For example, if you print the text variable as follows:

printf "%s" "${text:0:5}"
#Output
Hi! H
printf "%s" "${text:1:5}"
#Output
i! Ho
#and so on

If you wish to print all the string and remove each character from left per loop you can use this script:

#!/bin/bash

null=$'\0'
text="Hi! How are you doing on this fine evening? ${null}"

#while :; do
count=0
for (( i = 0; i < "${#text}"; i++ )); do
   printf "\r%s" "${text:$i}"
   sleep 0.3
done
#done
echo

The code above will print:

In first loop:

Hi! How are you doing on this fine evening?

In second loop:

i! How are you doing on this fine evening?

In third loop:

! How are you doing on this fine evening?

and so on.

Note: The variable $null should be used to avoid printing at the end of the string its last character, in this case ?. And if you want a infinite loop your should uncomment the lines #while :; do and #done.

0

echo -e "\r" is your friend: \r is the carriage return symbol (imagine you're sitting in front of a typewriter!) which puts your cursor back at the beginning of the current line.

So,

#!/bin/bash
echo -n "foobar"
#     ^---------- don't print a newline at the end of the line!
sleep 1
echo -e -n "\rbaz"
#        ^------- don't print a newline at the end of the line!
#     ^---------- evaluate escape sequences like \r
echo -e -n "\rB"

will print foobar, wait a second, then overwrite foo with baz and then directly overwrite the small with a capital B, yielding Bazbar.

That should be all you need for a scroller!

If you really want to do animations, this will end up being too complicated. You'd want to write a program that uses a library that can actually modify arbitrary positions on your terminal. (n)curses is such a library – even Python has a module for it! I'd recommend checking it out. Here's an example.

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .