使用 Windows Control-C 剪贴板副本时如何保留制表符 `n`n?

How can I keep tab characters `n`n when using Windows Control-C clipboard copy?

我有一些不寻常的、相对 complex/large PowerShell 脚本,它通过 Write-Host 输出彩色文本。我想将整个文本输出复制到 Windows 剪贴板而不丢失制表符(使用 windows Control-C,剪贴板复制)或替代。如果我在 PowerShell.exe 控制台 Window 中运行脚本后突出显示所有文本,然后按 control-C(复制到 Windows 剪贴板)制表符将转换为空格。

如果我尝试使用下面的 Set-Clipboard cmdlet 来传输我脚本的整个输出,我的脚本中有太多组件(主要是 Write-Host 行)与进一步 PS 不兼容流水线处理;因此,下面的 Set-Clipboard 将被完全忽略(仅将输出显示到本地主机控制台)。

PS:我也试过 Start-Transcript\Stop-Transcript.. 但是,那也没有捕获标签。它将制表符转换为空格。

我希望有人有一个聪明、快速的方法来剪贴板捕获我从需要写入主机的 cmdlet 中获得的文本,它还捕获 `t 制表符。

invoke-myscript -Devicename "WindowsPC" | Set-Clipboard
function Set-Clipboard {

param(
    ## The input to send to the clipboard
    [Parameter(ValueFromPipeline = $true)]
    [object[]] $InputObject
)

begin
{
    Set-StrictMode -Version Latest
    $objectsToProcess = @()
}

process
{
    ## Collect everything sent to the script either through
    ## pipeline input, or direct input.
    $objectsToProcess += $inputObject
}

end
{
    ## Launch a new instance of PowerShell in STA mode.
    ## This lets us interact with the Windows clipboard.
    $objectsToProcess | PowerShell -NoProfile -STA -Command {
        Add-Type -Assembly PresentationCore

        ## Convert the input objects to a string representation
        $clipText = ($input | Out-String -Stream) -join "`r`n"

        ## And finally set the clipboard text
        [Windows.Clipboard]::SetText($clipText)
    }
}

我认为您会找到的答案是使用 Write-Host 最总是会带您走上一条您不想要的路。 Jeffrey Snover 在他的博客中对此进行了讨论。更改脚本以将 Write-Host 更改为 Write-Output 甚至可能使用颜色来决定是否应将其中一些更改为 Write-Verbose and/or Write-Warning.

如果您这样做,那么您还有其他选择可供您使用,例如使用 -OutVariable 精确捕获输出以进行进一步处理(自动化)。

下面的示例展示了这样的更改如何使您受益。

function print-with-tab {
  [cmdletbinding()]
  Param()

  Write-Host "HostFoo`t`t`tHostBar"
  Write-Output "OutFoo`t`t`tOutBar"
  Write-Warning "You have been warned."
}

print-with-tab -OutVariable outvar -WarningVariable warnvar

Write-Output "Out -->"
$outvar
# proof there's tabs in here
$outvar -replace "`t", "-"
Write-Output "Warn -->"
$warnvar

输出

HostFoo         HostBar
OutFoo          OutBar
WARNING: You have been warned.
Out -->
OutFoo          OutBar
OutFoo---OutBar
Warn -->
You have been warned.

最后的想法

最后的想法是,如果您知道自己没有任何包含 4 个空格的字符串(如果这是您的制表符变成的内容),那么获取您的输出,将所有出现的 4 个空格替换回制表符,然后添加到剪贴板。 Hacky,但根据我之前关于 Write-Host 和进一步自动化所采取的路径的观点......这可能对你有用。

在那种情况下,我认为你可以使用类似的东西:

$objectsToProcess += $inputObject -replace "    ", "`t"

违背专家建议..我仍然觉得我的解决方案对我的情况来说是最简单(也是最理想)的解决方案。我不会轻率地做出这个决定;特别是当人们花大量时间试图帮助我时。对不起马特!如果我的庞大脚本中还没有一百万 write-host 行,我会使用您的解决方案。

使用简单的 search\replace 重构是最简单的解决方案(在我的例子中)。我可以将我的自定义命名为 write-host,例如 'Write-Host2'。然后,只需将 Write-Host2 函数添加到我的脚本中。它将向后兼容大多数 Write-Host 参数;另外,copy-paste 和制表符兼容颜色输出到本地控制台。