シェルスクリプト(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}"

ターミナル出力:コードがクリップボードにコピーされました。

スタンドアロンコマンド:

echo "\u2714 checkmark"

ターミナル出力: ✔チェックマーク

私の殻はzsh 5.8 (x86_64-debian-linux-gnu) 使用rxvt-Unicode-256color端末

答え1

あなたのshebangにはそれがあり/bin/sh、私はそれがあなたのシステムに存在すると思います/bin/sh。 Debian が承認した実装ではありません。とにかく、スクリプトで非標準構文を使用しないことをお勧めします。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があります。また、主に中国で使用されるUnicodeエンコーディングです(例:zh_CN.gb18030Debianのロケール)。

関連情報