この記事について
この記事は、生成AIを活用した自動生成フローで作成しています。.NETのString.NormalizeとNormalizationForm.FormKCの公式仕様を照合し、PowerShellからUnicode正規化を観察するサンプルを作成しました。PowerShell実機での実行確認は未実施です。
検証ステータス:📘 .NET公式仕様確認済み/PowerShell実機未確認
ExcelやCSVで「ABC123」と「ABC123」が混在すると、見た目はほぼ同じなのに別の値として比較されることがあります。半角カタカナや丸数字が混ざった場合も同様です。
.NETのString.NormalizeでNormalizationForm.FormKCを指定すると、Unicodeの互換正規化(NFKC)で多くの表記差を統一できます。ただし、NFKCには元の表記を復元できない変換もあるため、商品コード・社員ID・パスワードなどに無条件で適用してはいけません。
PowerShellで最小例を試す
PowerShell 7やWindows PowerShell 5.1など、.NETのString.Normalizeを使える環境を想定します。
$before = 'ABC123' $after = $before.Normalize([Text.NormalizationForm]::FormKC) "Before: $before" "After : $after"
期待される表示は次のとおりです。これは公式仕様から予想した結果であり、実機出力ではありません。
Before: ABC123 After : ABC123
FormKCは、互換分解と正準合成を行うNFKC正規化です。よく似たFormC(NFC)は主に正準等価を扱い、互換文字の統一とは用途が異なります。
いろいろな文字を比較する
次のサンプルでは変換前後を表にして、実際に内容が変わったか確認します。入力はダミー文字列のみで、ファイルやレジストリには書き込みません。
$values = @(
'ABC123'
'カタカナ'
'① Ⅳ'
)
$results = foreach ($original in $values) {
$normalized = $original.Normalize([Text.NormalizationForm]::FormKC)
[pscustomobject]@{
Before = $original
After = $normalized
Changed = ($original -cne $normalized)
}
}
$results | Format-Table -AutoSize
予想される変換は、ABC123→ABC123、カタカナ→カタカナ、① Ⅳ→1 IVです。丸数字やローマ数字の表記が変わることからも、単なるスペース削除や英数字の幅変更ではないと分かります。
同じコードはDaily-Code-SamplesのNFKC実験に保存しています。サンプルは読み取りと表示だけで、CSVを勝手に上書きしません。
1か所変更してNFCと比べる
FormKCをFormCに変えて同じ文字を比較します。
$text = 'ABC123' $text.Normalize([Text.NormalizationForm]::FormC) $text.Normalize([Text.NormalizationForm]::FormKC)
FormCでは全角英数字がそのままで、FormKCでは半角英数字へ統一されることが期待されます。どちらが「正解」というより、何を同じ文字として扱いたいかで選ぶものです。
.NET公式のString.NormalizeとNormalizationFormには正規化形式の説明があります。
仕事で使うなら「正規化前」を残す
例えば販売データの品名欄に、入力者によって全角と半角が混ざる場合、検索や集計のために正規化した別の列を追加すると便利です。
$rows = @(
[pscustomobject]@{ Item = 'ABC123'; Count = 2 }
[pscustomobject]@{ Item = 'ABC123'; Count = 3 }
)
$rows | Select-Object Item, Count, @{
Name = 'SearchKey'
Expression = {
$_.Item.Normalize([Text.NormalizationForm]::FormKC)
}
}
ここでは元のItemを保持し、新しいSearchKeyを追加しています。元データを失わないため、後から「同じ文字列として扱ってよいか」を確認できます。
注意: 異なる元の文字列が同じSearchKeyになることがあります。そのため、社員番号や商品コードで一意性を保証するなら、正規化後に重複が発生するか確認してからキーとして採用します。
誤って統一してはいけない例
| データ | NFKC適用の考え方 |
|---|---|
| 検索補助用の品名 | 元の文字列と別列で正規化を試せる |
| 入力された全角英数字の説明文 | 用途によっては統一が便利 |
| 商品コード・管理番号 | 正規化で別IDが衝突しないか検証が必要 |
| パスワード・署名対象 | 意味や照合結果が変わるため勝手に変更しない |
| ファイル名 | 既存のパスとの不一致や衝突を確認 |
また、Unicode正規化は「似て見えるすべての文字」を同一化するものではありません。異なる文字体系の見た目が似た文字や、不可視文字、末尾空白などをすべて解決する万能な処理ではありません。
失敗・境界条件
入力が$nullの場合、文字列メソッドをそのまま呼ぶと失敗します。CSVやAPIから受け取るデータでは、最初にnullかどうかを確認してください。
function ConvertTo-Nfkc([AllowNull()][string]$Value) {
if ($null -eq $Value) { return $null }
return $Value.Normalize([Text.NormalizationForm]::FormKC)
}
Unicodeの正規化に失敗する不正な文字列についても、業務で利用する場合には例外処理を検討します。さらにPowerShellの-eqなどの比較演算子は既定で大文字・小文字を区別しないため、ケースまで厳格に判定したい場合は-ceqや-cneを使います。
