쉘스크립트(zsh)에서 에코 체크 표시를 작동하는 방법

쉘스크립트(zsh)에서 에코 체크 표시를 작동하는 방법

에코만 올바르게 출력되는데도 쉘스크립트를 실행할 때 이 체크 표시가 올바르게 인쇄되지 않는 이유는 무엇입니까?

스크립트:

#!/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. 데비안이 승인한 구현이 아닙니다. 어쨌든 스크립트에서 비표준 구문을 사용하지 않는 것이 좋습니다.zshzshshshsh

\u2714표준 구문이 아닙니다 echo. 이것은 (아마도) POSIX 표준의 다음 주요 개정판에서 표준이 될 것이지만 or 에 대한 인수 $'...'에는 나타나지 않을 것이며 어떤 경우에도 데비안의 기본 구현( )은 이를 아직 지원하지 않습니다 .echoprintfshdash$'...'

\uXXXXzsh' printf(형식 인수에서 %b), print( aw 제외 -r) 및 echo(이 옵션이 활성화되거나 활성화되지 않은 경우 -E) bsdecho내장 함수와 그 내부( $'...'이러한 시퀀스가 ​​도입되는 첫 번째 셸임)로 인식되며 자체적으로 인용됩니다. ksh93에서).\uXXXX$'...'$'...'

#! /bin/zsh -스크립트에서 함수를 사용 하려면 zshshebang을 .

그런 다음 다음과 같은 더 많은 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실패로 간주되는 파이프를 사용할 수도 있습니다 .oathtoolxclipxclip

로케일의 문자 인코딩에 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데비안의 로케일).

관련 정보