powershell - 如何使用PowerShell将UTF-8字符传递给clip.exe,而无需转换为另一个字符集?

标签 powershell character-encoding

我是Windows和Powershell的新手。我来自Linux Land。我曾经在自己的.bashrc中拥有这个小Bash函数,该函数会为我复制一个“shruggie”(¯\_(ツ)_/¯)到剪贴板,以便我可以将其粘贴到Slack等上的对话中。

我的Bash别名如下所示:alias shruggie='printf "¯\_(ツ)_/¯" | xclip -selection c && echo "¯\_(ツ)_/¯"'
我意识到这个问题是青少年问题,但是答案对我来说确实很有值(value),因为我确信将来在某个时候需要将非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编码的,请确保将包含附件的文件另存为带有Windows PowerShell BOM的UTF-8。认识它。
  • 在没有BOM的情况下,Windows PowerShell将源解释为“ANSI”编码,指的是有效的旧版单字节扩展ASCII代码页,例如美式英语系统上的Windows-1252,因此错误地解释了UTF-8编码的源代码。
  • 请注意,相比之下,PowerShell Core使用UTF-8作为默认设置,因此不再需要BOM(但仍然可以识别)。


  • 使用¯\_(ツ)_/¯clip.exe复制到剪贴板:
  • Windows PowerShell v5.1 + 中,您可以使用内置的Set-Clipboard cmdlet 从PowerShell内部将文本复制到剪贴板;鉴于PowerShell使用能够表示所有Unicode字符的.NET System.String类型,因此不存在编码问题。
  • 请注意,即使在Windows上运行,PowerShell Core也没有此cmdlet(从PowerShell Core v6.0.0-rc.2开始)
  • 有关可在早期PowerShell版本以及PowerShell Core中运行的剪贴板功能的信息,请参阅我的this answer
  • 在Windows PowerShell的早期版本中和PowerShell Core 中,可以使用替代,但要使用则需要其他工作:

  • 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
    }
    
  • clip.exe创建New-Object System.Text.UnicodeEncoding $False, $False可以理解的无BOM的UTF16-LE编码。
  • 不幸的是,神奇的clip.exe咒语需要围绕bug来解决;在PSv5 +中,您可以改用以下命令来绕过此错误:.psobject.BaseObject
  • 将该编码分配给首选项变量[System.Text.UnicodeEncoding]::new($False, $False)可确保PowerShell使用该编码将数据通过管道传输到外部实用程序$OutputEncoding


  • clip.exe写入控制台:

    注意:Unix平台上的PowerShell Core通常使用默认编码为(无BOM)UTF-8的控制台(终端),因此在此无需进行其他工作。

    仅回显(打印)Unicode字符(超出8位范围),将切换到可以显示 Unicode字符(超出扩展的ASCII范围)的字体就足够了,因为PetSerAl指出了这一点,PowerShell uses the Unicode version of the ¯\_(ツ)_/¯ Windows API function打印到控制台。

    为了支持(最多)Unicode字符,大多数切换为“TT”(TrueType)字体之一。

    PetSerAl在评论中指出,Windows上的控制台窗口当前仅限于每个输出字符(单元)使用单个16位代码单元。鉴于BMP (Basic Multilingual Plane)中只有(大多数)字符是独立的16位代码单元,因此无法表示超出BMP的(稀有)字符。

    遗憾的是,即使对于某些(BMP)Unicode字符而言,这可能还不够,因为Unicode标准的已版本化,并且字体表示/实现可能会落后于

    确实,从Windows 10发行版ID 1703开始的,只有选择几种字体才能呈现 WriteConsole (Unicode字符KATAKANA LETTER TU,UTF-8:U+30C4):
  • E3 83 84
  • MS Gothic


  • 请注意,如果要(也)更改其他应用程序解释此类输出的方式,则必须再次设置NSimSum :

    例如,要使PowerShell期望来自外部实用程序的UTF-8输入以及将UTF-8编码的数据输出到外部实用程序,请使用以下命令:
    $OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding
    

    上面隐含地将代码页更改为$OutputEncoding(UTF-8),反射(reflect)在65001(chcp)中。

    请注意,为了向后兼容,Windows控制台窗口仍默认为单字节扩展ASCII旧OEM代码页,例如美国英语系统上的chcp.com

    不幸的是,从v6.0.0-rc.2开始,这也适用于PowerShell Core,即使它已经切换为无BOM的UTF-8作为默认编码,这也反射(reflect)在437中。

    关于powershell - 如何使用PowerShell将UTF-8字符传递给clip.exe,而无需转换为另一个字符集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48016113/

    相关文章:

    php - 检测 URL 查询字符串编码

    validation - 在创建 OU 之前检查它是否存在

    powershell - 启动进程 : Access is denied (even though i've provided credentials

    powershell - 按时间戳对行数组进行排序

    c# - Unicode 到 Mazovia 编码冗余字符

    php - 以下正确的字符编码是什么

    html - 如何对 HTML 正文中的引号进行编码?

    windows - 安装已删除的 Windows 功能

    visual-studio - 从命令行安装 VS.NET 扩展

    mysql - 由于语言编码,本地 mysql 导入文件 .sql 出现问题