저는 Bash로 작성된 Rubik's Cube 스톱워치를 작업 중이며 가능한 한 빨리 종료해야 할 때 Ctrl+를 사용할 수 없기 때문에 스페이스 바를 눌러 중지하고 싶습니다 .C
그럼 스페이스바만으로 프로그램을 멈출 수 있는 방법이 있을까요?
kill
나는 알 수 없어서 명령을 올려다보았다 .
코드의 스톱워치 부분은 다음과 같습니다.
TMP0=$(date +%s%N)
while true; do
TMP1=$(date +%s%N)
DTMP=$(($TMP1-$TMP0))
printf "\r$(($DTMP/1000000000)).${DTMP:(-9):2}"
done
답변1
Ctrl+를 누를 때 SIGINT를 전경 프로세스 그룹으로 보내는 것은 터미널입니다 c. 모든 캐릭터에 대해 이 작업을 수행하도록 구성할 수 있지만 스크립트가 종료되면 이전 설정을 복원하려고 합니다.
#!/bin/bash
settings="$(stty -g)"
trap 'stty "$settings"' EXIT
stty intr ' '
TMP0=$(date +%s%N)
while true; do
TMP1=$(date +%s%N)
DTMP=$(($TMP1-$TMP0))
printf '\r%s' "$(($DTMP/1000000000)).${DTMP:(-9):2}"
done
settings="$(stty -g)"
이전 설정을 저장합니다. stty intr ' '
터미널이 + Space대신 에 반응하도록 만듭니다 . 스크립트가 종료되면 이전 설정을 복원하는 일을 담당합니다.Ctrlctrap 'stty "$settings"' EXIT
노트:
트랩 코드에서는stty $settings
가stty "$settings"
. "의 예외입니다.항상 인용하다" 규칙. 인용은 단어 분할 및 파일 이름 생성(globbing)을 방지하지만 일부 구현에서는stty
단어 분할이 필요할 수 있으므로 변수를 인용하면 안 됩니다. 파일 이름 생성으로 인한 유해한 부작용을 방지하려면사양stty -g
이 기능을 트리거하지 않는 문자열을 생성 해야 합니다 .편집하다:그것은 POSIX 사양의 결함이었습니다. 위의 코드가 수정되었습니다.
문제가 발생하여 여전히 SIGINT를 생성하는 대화형 셸에 있는 경우 직접 Space호출해야 합니다 .
stty intr ^C
명령에 공백이 있지만 Ctrl+ 를 눌러 리터럴 공백 문자를 입력할 수 있다는 점을 기억하세요 v Space.printf '\r%s' …
나는 정적 형식과 동적 데이터가printf
귀하가 사용한 동적 형식보다 더 나은 "철학"에 적합하다고 생각하기 때문에 사용했습니다 .
" Space대신 Ctrl+ c"는 Space특별해지면 Ctrl+가 c더 이상 특별해지지 않음을 의미합니다. 당신은 그것을 결함이라고 부를 수도 있습니다.Ctrl사용자는 +가 c특별하게 유지되기를 기대합니다 .. 두 가지를 동시에 특별하게 만드는 것은 간단한 일이 아니지만 터미널 구성으로는 불가능하다고 생각합니다.
이 대체 버전은 거의 모든 키에서 중지되지만 Ctrl+는 c평소대로 작동합니다.
#!/bin/bash
while read -r -t 0.001; do :; done # dump the buffer
TMP0=$(date +%s%N)
until read -r -n 1 -t 0.001; do
TMP1=$(date +%s%N)
DTMP=$(($TMP1-$TMP0))
printf '\r%s' "$(($DTMP/1000000000)).${DTMP:(-9):2}"
done
echo
반응하게 하려면 Space읽은 내용을 확인해야 합니다.
…
until read -r -n 1 -t 0.001 && [ "$REPLY" = ' ' ]; do
…
Space이제 스크립트를 중지하는 메커니즘 은 Ctrl+가 c작동하는 방식과 매우 다릅니다.
답변2
스톱워치가 필요하지 않은 경우 어쨌든 결국 소요된 시간을 알고 싶다면 다음을 사용할 수 있습니다.
time read -r -n 1
다음과 같은 결과를 얻을 것입니다:
time read -r -n 1
real 1m30.909s
user 0m0.000s
sys 0m0.000s
거의 모든 키 입력으로 중지합니다(Kamil이 사용하는 방식과 유사 read
).
또는 시간 부분만 원하는 경우:
{ time read -r -n 1; } 2>&1 | grep real | awk '{ print $2 }'
의 호의리치