에코만 올바르게 출력되는데도 쉘스크립트를 실행할 때 이 체크 표시가 올바르게 인쇄되지 않는 이유는 무엇입니까?
스크립트:
#!/bin/sh
YELLOW='\033[1;33m'
NC='\033[0m' # no color
echo "enter your provider's auth code"
stty -echo
read authcode
oathtool --totp -b $authcode | xclip -i
echo "${YELLOW}\u2714 code copied to clipboard${NC}"
터미널 출력:\u2714 코드가 클립보드에 복사되었습니다.
독립 실행형 명령:
echo "\u2714 checkmark"
터미널 출력: ✔ 체크 표시
내 껍질은zsh 5.8 (x86_64-debian-linux-gnu) 사용rxvt-유니코드-256color단말기
답변1
당신의 shebang에는 그것이 있고 /bin/sh
, 나는 그것이 당신의 시스템에 존재한다고 생각합니다 /bin/sh
. 데비안이 승인한 구현이 아닙니다. 어쨌든 스크립트에서 비표준 구문을 사용하지 않는 것이 좋습니다.zsh
zsh
sh
sh
sh
\u2714
표준 구문이 아닙니다 echo
. 이것은 (아마도) POSIX 표준의 다음 주요 개정판에서 표준이 될 것이지만 or 에 대한 인수 $'...'
에는 나타나지 않을 것이며 어떤 경우에도 데비안의 기본 구현( )은 이를 아직 지원하지 않습니다 .echo
printf
sh
dash
$'...'
\uXXXX
zsh
' printf
(형식 인수에서 %b
), print
( aw 제외 -r
) 및 echo
(이 옵션이 활성화되거나 활성화되지 않은 경우 -E
) bsdecho
내장 함수와 그 내부( $'...'
이러한 시퀀스가 도입되는 첫 번째 셸임)로 인식되며 자체적으로 인용됩니다. ksh93에서).\uXXXX
$'...'
$'...'
#! /bin/zsh -
스크립트에서 함수를 사용 하려면 zsh
shebang을 .
그런 다음 다음과 같은 더 많은 zsh 기능을 사용할 수 있습니다.
print -P '%B%F{yellow}\u2714 whatever%f%b'
%F{yellow}
Rompt 확장을 사용하면 P
터미널의 올바른 코드로 확장되어 F
광석 색상을 다음으로 변경할 수 있습니다.노란색( %f
전경색을 기본값으로 재설정하고 %B
/ %b
활성화/비활성화용감한당신과 같습니다 \033[1m
.)
에서는 zsh
다음 작업도 수행할 수 있습니다.
IFS= read -rs 'authcode?enter auth code: '
보다 안정적으로 메시지를 표시하고 s
자동 입력을 활성화합니다.
어떤 경우든 에서와 같이 입력 손상을 sh
원 -r
하고 IFS=
방지 할 수 있습니다.read
set -o pipefail
실패하면 oathtool | xclip
실패로 간주되는 파이프를 사용할 수도 있습니다 .oathtool
xclip
xclip
로케일의 문자 인코딩에 U+2714 문자가 없으면 오류 print
와 함께 실패합니다 .zsh: character not in range
표준 sh
+ 유틸리티 구문에서 구문은 다음과 같아야 합니다.
#! /bin/sh -
bold_yellow='\033[1;33m'
nc='\033[m' # no color
if [ "$(locale charmap)" = UTF-8 ]; then
check_mark='\0342\0234\0224'
else
check_mark='[X]'
fi
saved_tty_settings=$(stty -g)
trap 'stty "$saved_tty_settings"' EXIT ALRM TERM INT QUIT
stty -echo
printf >&2 "enter your provider's auth code: "
IFS= read -r authcode &&
secret=$(oathtool --totp -b "$authcode") &&
printf %s "$secret" | xclip -i &&
printf '%b\n' "${bold_yellow}${check_mark} code copied to clipboard${nc}"
색상 이스케이프 시퀀스는 여기에 하드코딩되어 있으며, U+2714의 UTF-8 인코딩은 로케일의 문자 맵이 UTF-8인 경우에만 하드코딩됩니다.
아니면 이렇게 할 수도 있습니다:
check_mark=$(printf '\342\234\224' | iconv -f UTF-8 2> /dev/null) ||
check_mark='[X]'
check_mark
로케일에 대한 문자 맵이 존재하는 경우(그리고 UTF-8
시스템에서 이를 지원하는 경우) 가져오고, [X]
그렇지 않은 경우에는 해당 로케일의 문자 맵을 가져옵니다 . GB18030은 내가 아는 유일한 문자 맵으로 U+2714가 있습니다. 또한 주로 중국에서 사용되는 유니코드 인코딩입니다(예: zh_CN.gb18030
데비안의 로케일).