나는 어떤 쉘에서도 작동하는 결과를 얻기 위해 웹을 검색하고 기술을 테스트하는 데 10시간을 보냈습니다( #!/bin/sh
).
read
BASH에서는 잡아야 할 문자 수를 알고 구분 기호가 발견되면 즉시 종료되므로 비교적 간단합니다 .
stty -icanon -echo; echo -en "\033[6n"; read -d R -n 12 ESCPOS; stty "$x_TERM"; \
ESCPOS=`echo "$ESCPOS" | tail -c +3`; echo "$ESCPOS"
모든 쉘과 호환되는 sh 스크립트 버전을 작성하는 방법은 무엇입니까?
답변1
복사한 곳https://unix.stackexchange.com/a/88327
/bin/sh
POSIX를 사용한다고 가정합니다 sh
(Bourne 쉘을 사용할 수 있는 Solaris 10 및 이전 버전에서는 대신 이를 사용하십시오 /usr/xpg4/bin/sh
).
if [ -t 0 ] && [ -t 1 ]; then
old_settings=$(stty -g) || exit
stty -icanon -echo min 0 time 3 || exit
printf '\033[6n'
pos=$(dd count=1 2> /dev/null)
pos=${pos%R*}
pos=${pos##*\[}
x=${pos##*;} y=${pos%%;*}
stty "$old_settings"
fi
전체 응답이 한 번에 최대 0.3초 동안 대기한다고 가정합니다. 이는 일반적으로 터미널 에뮬레이터 및 pty 장치에 적용되지만 직렬 터미널에는 반드시 그런 것은 아닙니다. 8바이트를 읽을 때까지 계속 기다리 도록(각 바이트 간 최대 0.3초) 변경할 수 있지만 min 8 time 3
, 답이 8바이트보다 짧으면 항상 최소 0.3초가 걸리고, 답이 없을 경우에는 항상 0.3초가 걸린다는 단점이 있습니다. .
awk -F'[^0-9]+' -v RS=R '{print $3, $2; exit}'
와 함께 사용할 수 있습니다 min 1 time 0
. 이는 다른 구현 (입력 처리를 시작하기 전에 입력 데이터로 가득 찬 버퍼를 축적해야 함) awk
과 함께 사용할 수 있습니다 .mawk
결국 자신의 답변처럼 한 번에 한 바이트씩 읽는 것이 가장 안정적입니다. 응답을 보내지 않는 엔드포인트를 설명하기 위해 시간 제한을 추가해야 할 수도 있습니다.
답변2
노트:
unlike the wrongly copied and continually upvoted answer provided
(points scoring?), the following script IS NON-BLOCKING, and does
not care what length returned input may be. IE it will work with
ANY screen size.
SH를 사용하는 것은 더 복잡했고 내장된 향상된 명령줄 버전을 찾을 수 없었습니다. read
결국 STDIN에 대한 언급을 찾았고 dd
결과는 다음과 같습니다. 내장된 SH 버전은 사용할 수 있지만 echo
허용되지 않습니다 .echo -en
/bin/echo -en
printf
#!/bin/sh
x_TERM=`stty -g`
stty -icanon -echo
printf "\033[6n"
ESCPOS=""
X=""
I=0
while [ ! "$X" = "R" ]; do
X=`dd bs=1 count=1 2>/dev/null`
I=`expr $I + 1`
if [ $I -gt 2 -a ! "$X" = "R" ]; then
ESCPOS="$ESCPOS$X"
fi
done
stty "$x_TERM"
#echo "$ESCPOS"
CSRLIN=`echo "$ESCPOS" | cut -d \; -s -f 1`
POS=`echo "$ESCPOS" | cut -d \; -s -f 2`
echo "$CSRLIN"
#exit 0 <= dont use inline
나는 두 개의 서로 다른 스크립트에서 동일한 코드를 사용하고 있습니다. 하나는 출력용 CSRLIN
이고 다른 하나는 출력용입니다 POS
.
편집하다:. CSRLIN
이 스크립트를 다른 스크립트(예 : 셸이 대화형 모드에 있어야 하기 때문에) 에서 사용하려면 인라인해야 합니다 .
건배
폴