그래서 저는 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에도 모듈이 있습니다! 확인해 보시길 권합니다.이것은 예이다.