Powershell,无法输入包含某些非ASCII字符的哈希表键(在脚本中)

Powershell,无法输入包含某些非ASCII字符的哈希表键(在脚本中),powershell,utf-8,character-encoding,char,hashtable,Powershell,Utf 8,Character Encoding,Char,Hashtable,我正在尝试创建一个PowerShell哈希表,以将非ASCII UTF8字符转换为其ASCII外观 这里有两个哈希表条目作为示例:“ñ”='n”和“ñ”='n” 编者按:在同一个哈希表literal@{'ñ'='n';'ñ'='n'}中使用这两个条目是行不通的,因为PowerShell使用具有不区分大小写的键查找的哈希表,因此会考虑'ñ'和'ñ'重复键并进行投诉。然而,这是手头问题的附带问题 第一个有效:“ñ”是0xc3b1。第二个不起作用:“ñ”是0xc391,PowerShell不会接受。问

我正在尝试创建一个PowerShell哈希表,以将非ASCII UTF8字符转换为其ASCII外观

这里有两个哈希表条目作为示例:“ñ”='n”和“ñ”='n”

编者按:在同一个哈希表literal@{'ñ'='n';'ñ'='n'}中使用这两个条目是行不通的,因为PowerShell使用具有不区分大小写的键查找的哈希表,因此会考虑'ñ'和'ñ'重复键并进行投诉。然而,这是手头问题的附带问题

第一个有效:“ñ”是0xc3b1。第二个不起作用:“ñ”是0xc391,PowerShell不会接受。问题似乎是0x91超出了可接受的powershell字符的范围

一个简单的问题示例是:

$c = [convert]::toChar(0x91)
这导致$c获得的值为0x3f,而不是0x91。那么,我该怎么做才能让‘ñ’=‘N’进入
哈希表,还是值为0x91的字符?我已经花了数小时阅读网页和进行实验。

注意:默认情况下,由于使用不区分大小写的查找,PowerShell哈希表不支持仅是另一个哈希表大小写变体的键;因此,ñ和ñ——前者是后者的小写版本——不能同时用作键——见下一节

在内存中,所有PowerShell字符串都是UTF-16.NET字符串,它们能够表示所有Unicode字符,因此在哈希表中使用字符(如ñ)作为键不是问题

您描述的问题仅在PowerShell由于假定错误的字符编码而错误解释从文件读取的源代码时出现

您的症状表明您的源代码是UTF-8编码的,但该文件没有BOM,这会导致Windows PowerShell,但幸运的是,PowerShell[Core]v6+不再根据系统的活动旧版ANSI代码页(例如,美国英语系统上的Windows-1252,单字节编码)将该文件误解为编码

确保您的源代码文件保存为UTF-8并带有BOM[1],您的问题就会消失

您认为的Unicode码点0xc3b1和0xc391实际上是对应于ñ和ñ:和的真实码点的2字节UTF-8编码0xc3 0xb1和0xc3 91

至于:

[转换]::toChar0x91

似乎没有生成具有给定代码点0x91 decimal 145的[char]实例:

它确实存在,即在内存中,您可以轻松验证:

  [int] [convert]::toChar(0x91) # -> 145 (0x91)
您只会得到0x3f-这是一个文本?字符try[char]0x3f-如果您错误地将内存中的表示形式保存为ASCII编码:由于0x91超出了Unicode的ASCII子范围(从0x00到0x7f),因此无法在输出文件中表示它,替换字符是什么?使用

请注意,PowerShell的哈希表不区分大小写,因此您不能拥有仅为大小写变体的键:

必须直接使用.NET[hashtable]类型System.Collections.hashtable来创建区分大小写的哈希表:

# Create case-SENSITIVE hash table:
$ht = [hashtable]::new()
$ht['ñ'] = 'LATIN SMALL LETTER N WITH TILDE' 
$ht['Ñ'] = 'LATIN CAPITAL LETTER N WITH TILDE'
$ht现在有2个条目,$ht['ñ']和$ht['ñ']区分大小写检索值

相反,如果您使用了$ht=@{},即将哈希表初始化为一个常规的、不区分大小写的哈希表,那么您只会得到一个值为“拉丁文大写字母N加波浪号”的条目,因为第二个赋值$ht['ñ']=,只是更新了由第一条语句创建的不区分大小写的查找键


[1] 或者,使用UTF-16编码,它总是使用BOM;UTF-16LE表单在PowerShell中被错误地称为Unicode。

注意:默认情况下,由于使用不区分大小写的查找,PowerShell哈希表不支持仅是另一个哈希表大小写变体的键;因此,ñ和ñ——前者是后者的小写版本——不能同时用作键——见下一节

在内存中,所有PowerShell字符串都是UTF-16.NET字符串,它们能够表示所有Unicode字符,因此在哈希表中使用字符(如ñ)作为键不是问题

您描述的问题仅在PowerShell由于假定错误的字符编码而错误解释从文件读取的源代码时出现

您的症状表明您的源代码是UTF-8编码的,但该文件没有BOM,这会导致Windows PowerShell,但幸运的是,PowerShell[Core]v6+不再根据系统的活动旧版ANSI代码页(例如,美国英语系统上的Windows-1252,单字节编码)将该文件误解为编码

确保您的源代码文件保存为UTF-8并带有BOM[1],您的问题就会消失

您认为的Unicode码点0xc3b1和0xc391实际上是对应于ñ和ñ:和的真实码点的2字节UTF-8编码0xc3 0xb1和0xc3 91

至于:

[转换]::toChar0x91

似乎没有生成具有 给定代码点0x91十进制145:

它确实存在,即在内存中,您可以轻松验证:

  [int] [convert]::toChar(0x91) # -> 145 (0x91)
您只会得到0x3f-这是一个文本?字符try[char]0x3f-如果您错误地将内存中的表示形式保存为ASCII编码:由于0x91超出了Unicode的ASCII子范围(从0x00到0x7f),因此无法在输出文件中表示它,替换字符是什么?使用

请注意,PowerShell的哈希表不区分大小写,因此您不能拥有仅为大小写变体的键:

必须直接使用.NET[hashtable]类型System.Collections.hashtable来创建区分大小写的哈希表:

# Create case-SENSITIVE hash table:
$ht = [hashtable]::new()
$ht['ñ'] = 'LATIN SMALL LETTER N WITH TILDE' 
$ht['Ñ'] = 'LATIN CAPITAL LETTER N WITH TILDE'
$ht现在有2个条目,$ht['ñ']和$ht['ñ']区分大小写检索值

相反,如果您使用了$ht=@{},即将哈希表初始化为一个常规的、不区分大小写的哈希表,那么您只会得到一个值为“拉丁文大写字母N加波浪号”的条目,因为第二个赋值$ht['ñ']=,只是更新了由第一条语句创建的不区分大小写的查找键


[1] 或者,使用UTF-16编码,它总是使用BOM;UTF-16LE格式在PowerShell中被错误地称为Unicode。

根据PowerShell,[char]0xc391是韩语字符sselt쎑, 请尝试[char]0x00D1,它是utf-16字符。这回答了你的问题吗@7cc不是关于Unicode而不是哈希表中的重复元素吗?Powershell 7给出了一个更好的错误消息:哈希文本中不允许重复键“ñ”。@NekoMusume utf16和Unicode是两个不同的东西,但microsoft使它混淆了Powershell,[char]0xc391是韩文字符sselt쎑, 请尝试[char]0x00D1,它是utf-16字符。这回答了你的问题吗@7cc不是关于Unicode而不是哈希表中的重复元素吗?Powershell 7给出了一个更好的错误消息:哈希文本中不允许重复键“ñ”。@NekoMusume utf16和Unicode是两个不同的东西,但microsoft使其混淆