使用 PowerShell 的 Unicode 规范化 NFKC 统一全角英数字 —— 不破坏原始数据的方法

PowerShellカテゴリを表すパンダのイラスト PowerShell

关于本文
本文是通过利用生成式 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 中尝试最小示例

假设环境支持使用 .NET 的(例如 PowerShell 7 或 Windows PowerShell 5.1等)。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。

修改一处并与 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。

官方资料

文档信息

文章??
使用 PowerShell 的 Unicode 规范化 NFKC 统一全角英数字 —— 不破坏原始数据的方法
?布日期
更新日期
来源
https://papanda925.com/?p=18094&lang=zh

?可: ?于本站?有相??利的正文及原??表,除非?有?明,可依据 CC BY 4.0 使用。本文可能包含使用生成式AI?建或??的内容。若代??有?可声明,或?接的GitHub???定了?可,?代?以??可?准。引用内容、第三方?料、?片及商?不在本?可范?内。 使用政策

标题和URL已复制