다음 bash 스크립트는 1..1000의 높은 개수 범위에서 작동합니다.
카운트 범위가 1..1000000보다 높기 때문에 시작하는 데 시간이 걸립니다. 전반적으로 잘 작동합니다.
for i in {1..10}; do
printf '\r%2d' $i
sleep 1
done
printf '\n'
99..1부터 시작하는 숫자 범위의 역수에 대해서는 잘 작동합니다.
99 이상에서 시작하는 숫자 범위를 카운트다운하기 위해 pe 100..1 출력은 0이 포함된 숫자를 너무 많이 인쇄합니다. 이것을 어떻게 피할 수 있습니까?
답변1
귀하의 질문:
명령을 시작하는 데 시간이 좀 걸립니다. 이는 루프에 사용한 버팀대 확장 때문입니다. 확장이 먼저 이루어져야 합니다.확장하다, 이는 쉘이 반복할 범위의 모든 숫자를 포함하는 목록을 생성해야 함을 의미합니다. 이를 위해서는 시간(목록 생성)과 메모리(목록 저장)가 필요합니다. 내 컴퓨터에서
bash
프로세스가 성장하는 것을 볼 수 있습니다.약 1400KiB에서 256MiB까지내가 목록을 생성하도록 요청할 때{1..1000000}
.대신, 산술 루프를 사용하는 것을 고려해 보세요.
for (( i=1000000; i >= 1; --i )); do ...; done
또는 POSIX 호환 루프,
i=1000000 while [ "$i" -ge 1 ]; do ...; i=$(( i - 1 )); done
두 방법 모두 정적 숫자 목록을 반복하지 않고 대신 테스트 값을 기반으로 루프 본문을 실행한 다음 테스트가 성공하면
$i
각 반복에서 변수 값을 감소시킵니다.1
i
각 숫자 끝에는 "추가 0"이 있습니다. 캐리지 리턴 문자를 출력하여 커서를 줄의 시작 부분으로 다시 이동시키기 때문입니다. 커서는 이동하지만 줄은 지워지지 않으므로 새 숫자의 자릿수가 더 적더라도 마지막 출력 숫자의 끝은 계속 표시됩니다.
이 문제를 해결하려면 다음을 사용해 보십시오.VT100 이스케이프 코드
\e[2K
커서를 줄의 시작 부분( )으로 이동하기 전에 전체 줄을 지우는 데 사용됩니다.for (( i=1000000; i >= 1; --i )); do printf '\e[2K\r%d' "$i" sleep 1 done printf '\n'
\e[1K
커서 왼쪽의 줄 영역을 지우는 것처럼 작동합니다. 또는\r%d\e[0K
명확한 선을 사용하십시오옳은숫자 출력 후 커서의 위치입니다.
답변2
당신이 보는 문제는 먼저 쓴 100
다음 같은 위치에서 시작하지만 출력 형식에 두 자리만 지정한다는 것 99
입니다 .1
%2d
지우기 지침을 제공하지 않았으므로 이것이 표시됩니다. 하지만 모두 한 줄에 있습니다.
What # What
you # was
see # output
100 # 100
990 # 99
980 # 98
...
90 # 9
80 # 8
...
10 # 1
세 자리 숫자로 형식을 지정하거나 공백 접미사를 추가해야 합니다.
printf "\r%3d" $i # One option
printf "\r%2d " $i # Another option
답변3
한 문자열을 다른 문자열로 바꾸려면 두 문자열이 모두 동일한 크기(또는 인쇄할 수 없는 문자(공백?)가 더 길어야 함)가 필요합니다.
123
인쇄된 내용을 로 바꾸면 처음에 인쇄하는지 아니면 끝에서 인쇄하는지에 따라 또는 을 7
얻게 됩니다 .723
127
이를 수행하려면(동일한 크기의 문자열) 다음 중 하나를 수행할 수 있습니다.
- 안정적인 크기의 버팀대 확장을 사용합니다.
{000..123}
- 전체 공간을 채우려면 printf를 사용하십시오.
printf '\r%5s' "$i"
- 긴 공백 문자열을 인쇄합니다.
printf '\r%s ' "$i"
- 줄이 끝날 때까지 줄을 지웁니다.
printf '\r%s\e[K' "$i"
- 전체 줄을 지우고 값을 인쇄합니다.
printf '\e[2K\r%s' "$i"
그러나 {1..1000000}을 사용하는 것은 메모리에 저장하고 공백으로 나눈 다음 루프에서 사용해야 하는 긴 숫자 문자열을 생성하기 때문에 최상의 솔루션이 아닙니다. Bash의 더 나은 솔루션은 다음과 같습니다.
for(( i=1; i<1000; i++ )); do
printf '\r%5d' $i
sleep 0.01
done
echo