Bourneシェルと互換性のある「${#string}」では、文字列の「長さ」はどのくらいですか?

Bourneシェルと互換性のある「${#string}」では、文字列の「長さ」はどのくらいですか?

~からこれ議論する:

私は(zsh 5.8、bash 5.1.0)

var="ASCII"
echo "${var} has the length ${#var}, and is $(printf "%s" "$var"| wc -c) bytes long"

答えは簡単です。 5文字で5バイトを占めます。

var=Müller、出力は

Müller has the length 6, and is 7 bytes long

これは${#}、演算子がバイトではなくコードポイントを計算することを示します。これは少し不明です。POSIXでは、彼らは「文字」を計算すると言います。char一般に、POSIX Cの文字がオクテットでない場合、これはより明確です。

とにかく:悪くないです!幸いにも私はそれを見たLANG==en_US.utf8

今、

var='

答え1

POSIX準拠のシェル(Bourneシェルではなく、機能はKornシェルで提供されています)からの計算と${#var}同じです。wc -m数値¹ in$varで格納されたバイトシーケンスを$var現在のロケールの文字でデコードできない場合、動作は指定されません。

現在のロケール(該当するカテゴリ)に従ってLC_CTYPEバイトを文字としてデコードします。文字エンコーディングでUTF-8を使用するロケールでは、0xc3 0xa9シーケンスが文字でデコードされ、ISO8859-1を使用するロケールではシーケンスがéé

とにかく、Unicodeコードポイントとはほとんど関係ありません。また、端末や他のディスプレイデバイスに表示されるときに文字クラスターの数や文字列の幅を計算することとは異なります。

存在する:

var="e\xcc\x81"

$vare、、、、、、、、\および9xバイトと9文字をc含みます。c\x81

一部printf(formatパラメータまたは%bformatディレクティブのパラメータ)とecho実装は0xccバイトに拡張されますが、\xccすべてではありません。 POSIXでは、\xこれらの議論は未指定の動作を引き起こします。 (型パラメータおよび/から\3510xe9バイトに拡張されます)。printf\0351echo%b

//(最近ではますます多くのシェル)に、、バイトを含めるには$var次のようにします。0x650xcc0x81ksh93zshbash

var=$'e\xcc\x81'

または、いつでも次のようにすることができます。

var=$(printf 'e\314\201')

locale charmapこれにより、出力ロケールには3バイト(など)、2つの文字(またはなど)、1つの子クラスタ(GNUのように)がUTF-8含まれ、通常は幅が1(表示されているGNUのように)で表示されます。$varwc -cwc -m${#var}grep -Po '\X'wc -L

シェルが呼び出され、コードが解析され実行されたときにロケールに文字セットとしてUTF-8がある場合は、複数のシェルで次のこともできます。

var=$'e\u0301'

およびU + 0301(グレードアクセントの組み合わせ)を含む文字の$varUTF-8エンコーディング。e

ロケールの文字セットが UTF-8 でない場合、動作はシェルによって異なります。また、シェルに従ってUnicodeコードポイントを文字に拡張するときにコードを解析するときに適用されるロケールを考慮するのか、コードを実行するときに適用されるロケールを考慮するのかを考慮します。その地域の真のマップにキャラクターが存在しない場合でも、動作の変化を確認できます。

Bourneシェルから文字列の文字長を取得するには、次のような他のユーティリティを使用する必要があります。

length=`expr "x$var" : '.*' - 1` || :

または:

length=`printf %s "$var" | wc -m`

ただし、まだBourneシェルを持つ古いシステムを見つけた場合、そのシステムはコマンドをサポートしていないかwc含まない-m可能性があります。printf


1 POSIX自体は、バイトシーケンスと文字シーケンス間のマッピングを指定せず、POSIXロケールでも一部のAPIのみがマッピングを定義および検索するため、またはバイトシーケンスを文字シーケンスに変換するために使用されます(wchar_t)。システムは通常、他のISO規格(ISO / IEC 10646、別名Unicode)で定義されている文字セット変換形式であるUTF-8などの文字セット標準文字セットを使用します。 GNUシステムなどの一部のシステムでは、wchar_tロケールに関係なく、Unicodeコードポイントを実際に値として使用します。

関連情報