Bash - 美观地滚动字符串

Bash - 美观地滚动字符串

因此,我尝试使用 bash 在控制台中创建美观的水平滚动文本。我不知道该怎么做。这是一个例子:

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

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

等等。我该怎么办呢?我最好让它删除最后一个打印的循环,这样它就是一个平滑的滚动字符串。任何帮助,将不胜感激!谢谢! (也请随意提问,这个描述有点糟糕:P)

答案1

这个有点hacky,但我相信这就是你所描述的效果。在输出中,每一行都会覆盖前一个条目,以便它生成类似于旧<marquee> 标签的内容,但在终端中。

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

将其保存在文件中并运行它,您应该看到字符串"Hello There!"滚动过去。这有点紧张,但你可以调整它以使其更整洁。

答案2

正如其他人所说,您应该使用echoorprintf和回车符\r

因此,您想要的是每个循环仅打印 5 个字符,您可以使用下面的脚本来实现该行为:

#!/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

通过这一行,printf "\r%s" "${text:$i:5}"我每个循环打印 5 个字符,其中 是$i当前索引,5是要打印的字符串的长度。
例如,如果text按如下方式打印变量:

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

如果您希望打印所有字符串并删除每个循环左侧的每个字符,您可以使用以下脚本:

#!/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

上面的代码将打印:

在第一个循环中:

Hi! How are you doing on this fine evening?

在第二个循环中:

i! How are you doing on this fine evening?

在第三个循环中:

! How are you doing on this fine evening?

等等。

笔记:应使用该变量$null来避免在字符串末尾打印其最后一个字符,在本例中为?。如果您想要无限循环,您应该取消注释行#while :; do#done

答案3

echo -e "\r"是你的朋友:\r 是回车符号(想象你正坐在打字机前!),它将你的光标放回到当前行的开头。

所以,

#!/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"

将打印foobar,稍等一下,然后foo用覆盖baz,然后直接用大写覆盖小的B,产生Bazbar

这应该就是你所需要的滚动条了!

如果你真的想做动画,这会变得太复杂。您想要编写一个使用库的程序,该库实际上可以修改终端上的任意位置。 (n)curses 就是这样一个库——甚至 Python 也有一个模块!我建议检查一下。这是一个例子

相关内容