我是Windows和Powershell noobie。我来自Linux Land。我以前在我的.bashrc
中有这个小Bash功能,它会将“shruggie”(¯\_(ツ)_/¯
)复制到剪贴板上,以便我可以将它粘贴到Slack等对话中。
我的Bash别名看起来像这样:alias shruggie='printf "¯\_(ツ)_/¯" | xclip -selection c && echo "¯\_(ツ)_/¯"'
我意识到这个问题是少年,但答案确实对我有价值,因为我确信我将需要在未来的某个时刻将非UTF-8字符输出到Powershell脚本中输出。
我在PowerShell配置文件中编写了这个函数:
function shruggie() {
'¯\_(ツ)_/¯' | clip
Write-Host '¯\_(ツ)_/¯ copied to clipboard.' -foregroundcolor yellow
}
但是,当我在命令行上调用它时,这给了我:??\_(???)_/??
(未知的UTF-8字符被转换为?
)。
我看过[System.Text.Encoding]::UTF8
和一些other questions,但我不知道如何将我的字符串转换为UTF-8并通过clip.exe
传递并在另一边(在剪贴板上)接收UTF-8。
有两个截然不同的独立方面:
¯\_(ツ)_/¯
将clip.exe
复制到剪贴板¯\_(ツ)_/¯
到控制台先决条件:PowerShell必须正确识别源代码的编码才能使下面的解决方案正常工作:如果源代码是UTF-8编码的,请务必将封装文件保存为带有BOM的UTF-8,以便Windows PowerShell识别它。
¯\_(ツ)_/¯
to the clipboard, using clip.exe
:Set-Clipboard
cmdlet将文本从PowerShell中复制到剪贴板;鉴于PowerShell使用能够表示所有Unicode字符的.NET System.String
类型,因此没有编码问题。
请注意,即使在Windows上运行,PowerShell Core也没有此cmdlet(从PowerShell Core v6.0.0-rc.2开始)
请参阅我的this answer,了解适用于早期PowerShell版本以及PowerShell Core的剪贴板功能。clip.exe
是一种可行的替代方案,但其使用需要额外的工作:function shruggie() {
$OutputEncoding = (New-Object System.Text.UnicodeEncoding $False, $False).psobject.BaseObject
'¯\_(ツ)_/¯' | clip
Write-Verbose -Verbose "Shruggie copied to clipboard." # see section about console output
}
New-Object System.Text.UnicodeEncoding $False, $False
创建了一个无BOM的UTF16-LE编码,clip.exe
可以理解。
不幸的是,奇怪的.psobject.BaseObject
咒语需要在bug周围工作;在PSv5 +中,您可以通过使用以下代码来绕过此错误:
[System.Text.UnicodeEncoding]::new($False, $False)
$OutputEncoding
可确保PowerShell使用该编码将数据传输到外部实用程序clip.exe
。¯\_(ツ)_/¯
to the console:注意:Unix平台上的PowerShell Core通常使用默认编码为(无BOM)UTF-8的控制台(终端),因此不需要额外的工作。
仅仅回显(打印)Unicode字符(超出8位范围),切换到可以显示Unicode字符的字体(超出扩展的ASCII范围)就足够了,因为正如PetSerAl指出的那样,PowerShell uses the Unicode version of the WriteConsole
Windows API function要打印到安慰。
要支持(大多数)Unicode字符,您最常切换到“TT”(TrueType)字体之一。
PetSerAl在一条评论中指出,Windows上的控制台窗口目前仅限于每个输出字符(单元格)一个16位代码单元;由于BMP (Basic Multilingual Plane)中只有(大多数)字符是自包含的16位代码单元,因此无法表示BMP之外的(罕见)字符。
遗憾的是,即使这对于某些(BMP)Unicode字符来说可能还不够,因为Unicode标准是版本化的,并且字体表示/实现可能会滞后。
实际上,从Windows 10发行版ID 1703开始,只有少数几种字体可以呈现ツ
(Unicode字符KATAKANA LETTER TU
,U+30C4
,UTF-8:E3 83 84
):
MS Gothic
NSimSum
请注意,如果您想(也)更改其他应用程序解释此类输出的方式,则必须再次设置$OutputEncoding
:
例如,要使PowerShell期望从外部实用程序输入UTF-8以及将UTF-8编码数据输出到外部实用程序,请使用以下命令:
$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding
上面隐含地将代码页更改为65001
(UTF-8),如chcp
(chcp.com
)中所反映的那样。
请注意,为了向后兼容,Windows控制台窗口仍默认为单字节,扩展ASCII旧版OEM代码页,例如美国英语系统上的437
。
不幸的是,从v6.0.0-rc.2开始,这也适用于PowerShell Core,即使它已经切换到无BOM的UTF-8作为默认编码,也反映在$OutputEncoding
中。
如果您不能使用PowerShell 5的Set-Clipboard
函数(这是IMO的首选解决方案),您可以以clip.exe
正确理解它的方式转换/编码您的输出。
有两种方法可以实现这里的目标:
clip < UTF16-Shruggie.txt
这里重要的部分是保存编码为的文件:Unicode
(这意味着UTF-16格式little-endian byte order与BOM)[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
function shruggie() {
[System.Text.Encoding]::Default.GetString(
[System.Text.Encoding]::UTF8.GetBytes('¯\_(ツ)_/¯')
) | clip.exe
Write-Host '¯\_(ツ)_/¯ copied to clipboard.' -foregroundcolor yellow
}
shruggie
这适合我。这是一个MSDN blog post,进一步解释有关$OutputEncoding
/ [Console]::OutputEncoding
。
帖子Set-Clipbord选项是最直接的答案,但正如PoSHv5和更高的东西所指出的那样。但是,根据OP所使用的操作系统,并非所有OS / PoSH版本都提供所有cmdlet。这并不是说Set-Clipboard不是,但由于OP说它们是新的,它只是一个抬头。
如果由于某种原因无法去那里,您可以创建自己的或使用附加模块。看这篇文章:
Convert Keith Hill's PowerShell Get-Clipboard and Set-Clipboard to a PSM1 script
使用上面帖子中的Set-Clipboard函数并修改OP的帖子以供其使用的结果:
(Get-CimInstance -ClassName Win32_OperatingSystem).Caption
Microsoft Windows Server 2012 R2 Standard
$PSVersionTable
Name Value
---- -----
PSVersion 4.0
WSManStackVersion 3.0
SerializationVersion 1.1.0.1
CLRVersion 4.0.30319.42000
BuildVersion 6.3.9600.18773
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion 2.2
function Set-ClipBoard
{
Param
(
[Parameter(ValueFromPipeline=$true)]
[string] $text
)
Add-Type -AssemblyName System.Windows.Forms
$tb = New-Object System.Windows.Forms.TextBox
$tb.Multiline = $true
$tb.Text = $text
$tb.SelectAll()
$tb.Copy()
}
function New-Shruggie
{
Set-ClipBoard -text '¯\_(ツ)_/¯'
Write-Host '¯\_(ツ)_/¯ copied to clipboard.' -foregroundcolor yellow
}
New-Shruggie
¯\_(ツ)_/¯ copied to clipboard.
Results pasted from clipboard
¯\_(ツ)_/¯
但是有一些选项,例如以下,但上述仍然是最佳途径。
首先要记住,输出由OS代码页和解释器(PoSH)控制,并且都默认为ASCII。
您可以通过查看内置变量的输出来查看PoSH默认CP设置
$OutputEncoding
根据PoSH创建者Jeffery Snover所说:我们在管道到现有可执行文件时转换为ASCII的原因是今天的大多数命令都没有正确处理UNICODE。 有些人做,大多数做不到。
所以,所有这一切......你可以改变CodePage,做像......这样的项目
[Console]::OutputEncoding
要么 ...
$OutputEncoding = New-Object -typename System.Text.UTF8Encoding
如果将输出发送到文件...
$OutPutData | Out-File $outFile -Encoding UTF8