PowerShell では内部的に UTF-16LE を利用しています。そのため、Windows API や Java を利用した開発と同様、文字列を取り扱う際にはサロゲートペア文字に関する問題を考慮しなければなりません。
String.Length
で文字数を数えてみる
まずは素直に String.Length
で文字数を数えてみましょう:
基本多言語面内(非サロゲートペア文字)
"a".Length
# 1
"あ".Length
# 1
基本多言語面外(サロゲートペア文字)
"🎵".Length
# 2
サロゲートペア文字の場合はハイサロゲート・ローサロゲートで合計2文字のカウントになっていますね。
同様に、結合文字列についても確認してみましょう:
結合文字列
"ぬ゙".Length
# 2 (1+1)
"👨🏻🎤".Length
# 7 (2+2+1+2)
結合に利用した分の文字数(サロゲートペア文字の場合は2文字として)でカウントされていますね。
なお、PowerShell には Linux 版もリリースされていますが、こちらでも同じ挙動となります。
$ docker run --rm mcr.microsoft.com/powershell:lts-7.2-debian-buster-slim pwsh -Command '"👨🏻🎤".Length'
7
StringInfo.LengthInTextElements
で文字数を数えてみる
System.Globalization.StringInfo
はサロゲートペア文字や結合文字列を考慮しながら文字列を取り扱うためのクラスです。コンストラクタでインスタンスを生成した後、LengthInTextElements
プロパティで以下の要素数を数えます:
- 基本文字
- サロゲートペア文字
- 結合文字列
[System.Globalization.StringInfo]::new("👨🏻🎤<ぬ゙~🎵").LengthInTextElements
# 5
やったね。期待通り 5 文字として数えることができました!
参考リンク
- 文字エンコードについて - PowerShell | Microsoft Learn
- String クラス (System) | Microsoft Learn
- String.Length プロパティ (System) | Microsoft Learn
- StringInfo.LengthInTextElements プロパティ (System.Globalization) | Microsoft Learn
- サロゲート文字と補助文字 | Microsoft Learn
- 文字列の長さ(文字数)を取得する - .NET Tips (VB.NET,C#...)
- サロゲートペア・結合文字列・合字
- 絵文字👨🏻🦱は何文字としてカウントする?関連する文字コードの仕様を詳しく調べてみた
- UTF-16
- 基本多言語面
- 結合文字
- 合成済み文字
- カオス過ぎる Unicode, UTF-8, UTF-16, UTF-32 の違い概要まとめ