터미널의 형식이 .txt 문서의 형식과 다릅니다.

터미널의 형식이 .txt 문서의 형식과 다릅니다.

시간을 추적하는 스크립트가 있습니다.

콘솔에 출력을 인쇄하면 다음과 같은 결과가 나타납니다.

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'

관련 정보