시간을 추적하는 스크립트가 있습니다.
콘솔에 출력을 인쇄하면 다음과 같은 결과가 나타납니다.
0 Days, 00:00:33
txt 파일로 저장하면 다음과 같은 결과가 나옵니다.
^[[2K
0 Days, 00:00:33
암호:
now=$(date +%s)
diff=$(($now - $begin))
mins=$(($diff / 60))
secs=$(($diff % 60))
hours=$(($diff / 3600))
days=$(($diff / 86400))
printf "\33[2K\r%3d Days, %02d:%02d:%02d" $days $hours $mins $secs
printf "\33[2K\r%3d Days, %02d:%02d:%02d" $days $hours $mins $secs >> test.txt
그것은 어디서 왔는가 ^[[2K
? 나는 이것이 printf의 형식화와 관련이 있다고 생각합니다.
여기에서 printf에 대한 내용을 읽었습니다.http://wiki.bash-hackers.org/commands/buildin/printf. 하지만 나는 더 현명하지 않습니다…
답변1
printf
명령에 이스케이프 제어 시퀀스가 있습니다 printf "\33[2K.....
(예: \e[2K
줄 지우기). 이는 터미널의 제어 명령이어야 하며 터미널 장치에서만 이해하고 실행할 수 있습니다.
터미널 내에서 스크립트를 대화형으로 실행하면 터미널이 시퀀스를 올바르게 해석합니다. 명령의 출력을 파일에 저장할 때 현재 시퀀스를 해석할 내용이 없기 때문에 시퀀스는 문자 그대로 처리됩니다.
이제 이렇게 하면:
cat test.txt
출력을 인쇄하기 전에 터미널이 시퀀스를 다시 올바르게 해석하는 것을 볼 수 있습니다.
답변2
선의 연속성
printf "\33[2K\r%3d Days, %02d:%02d:%02d" $days $hours $mins $secs
printf "\33[2K\r%3d Days, %02d:%02d:%02d" $days $hours $mins $secs >> test.txt
인쇄 시간 정보로 정의됩니다.같은 줄터미널. 저것\33[2K
전체 (현재) 행을 지우고\r
커서를 줄의 시작 부분으로 이동합니다. 그 효과는 시간 정보를 변경하여 변경된 것처럼 보이게 하는 것입니다.저것라인의 일부.
개행 문자가 없다는 것을 알았습니다(\n
) 형식. 질문에는 개행 문자가 표시됩니다(명확성을 위해 추가되었을 수도 있음).
답변3
다음과 같이 직접 작성하셨습니다.
\33[2K
터미널에 따라 이를 무언가를 수행하라는 지시로 이해합니다. "콘솔"을 언급했으므로 console_codes(4)
다음 목록이 나열된 매뉴얼 페이지를 확인할 수 있습니다.
ECMA-48 CSI 시퀀스
CSI
(또는ESC [
) 다음에 최대 일련의 매개변수가 옵니다.국립공원 서비스(16)은 세미콜론으로 구분된 십진수입니다. 비어 있거나 존재하지 않는 매개변수는 0으로 처리됩니다. 매개변수 순서 앞에는 물음표가 올 수 있습니다....
K
: EL - 줄 지우기기본값: 커서부터 줄 끝까지.
ESC [ 1 K
: 해당 줄의 처음부터 커서까지의 내용을 삭제합니다.
ESC [ 2 K
: 전체 줄을 삭제합니다.
(이것은 회상 \033
과 동일성 에 도움이 됩니다 ESC
).
따라서 이스케이프 시퀀스는 해당 터미널에 대한 "전체 줄 지우기" 명령입니다.
이 코드를 작성하는 이식 가능하고 깔끔한 방법은 다음과 같습니다.
clear_line=`tput cr; tput el`
printf "${clear_line}%3d Days, %02d:%02d:%02d" $days $hours $mins $secs
사용은 작업을 tput
지원하지 않는 터미널 el
이나 다른 이스케이프 시퀀스를 사용하여 이를 지원하는 터미널에 쓸 때 이해할 수 없는 쓰레기 대신 적절한 출력을 얻게 된다는 것을 의미합니다.
PS GNU를 가정하면 이 모든 산술은 아마도 불필요할 것입니다 date
. 7일을 넘지 않으면 7일로 줄일 수 있습니다.
date -u -d "-$begin seconds +3days" '+${clear_line}%w days, %T'
그렇지 않으면 여전히 계산이 필요 $days
하지만 다음을 사용하여 초 형식을 지정할 수 있습니다 %T
.
now=$(date +%s)
diff=$(($now - $begin))
days=$(($diff / 86400))
date -u -d "00:00 $diff seconds" '+${clear_line}$days days, %T'