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

이것은 약간 해킹적이지만 이것이 당신이 설명하는 효과라고 믿습니다. 출력에서 각 줄은 이전 항목을 덮어쓰므로 <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

다른 사람들이 말했듯이 echo또는 printf및 캐리지 리턴을 사용해야 합니다 \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에도 모듈이 있습니다! 확인해 보시길 권합니다.이것은 예이다.

관련 정보