【问题标题】:How can I make `Tee-Object` not adding a trailing newline in PowerShell?如何使 `Tee-Object` 不在 PowerShell 中添加尾随换行符?
【发布时间】:2022-01-17 19:17:01
【问题描述】:

Tee-Object 没有 -NoNewline 开关,就像许多其他输出到文件的 cmdlet(例如 Out-FileSet-Content)一样。 Under the hoodTee-Object 使用 Out-File 写入文件,默认情况下添加尾随换行符。

由于我(当前)无法通过Tee-Object 切换-NoNewline,是否有另一种方法可以强制底层Out-File 不会添加尾随换行符?看看implementation of Out-File,现在可能有办法,但也许有人知道一些技巧/黑客来实现它?

一些限制:

  • 我想在管道中使用Tee-Object(或替代解决方案)
  • 我不想对Tee-Object(或其他解决方案)生成的文件进行后处理,例如再次打开它们并删除(最后一个)换行符。

复制代码:

"Test" | Tee-Object file | Out-Null

在 Windows 上,生成的文件 file 将包含 6 个字节,如以下 hexdump 所示:

          00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ASCII
00000000  54 65 73 74 0D 0A                               Test..

不幸的是,其中包含额外的字节0D 0A a。 ķ。一种。 `r`n 或 Windows 中的 CR&LF。

【问题讨论】:

    标签: powershell newline tee trailing-newline powershell-7.2


    【解决方案1】:

    您可以自己滚动并编写一个带前缀的换行符:

    function Tee-StackProtectorObject {
        param(
            [Parameter(Mandatory=$true, Position=1, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
            [AllowNull()]
            [AllowEmptyCollection()]
            [psobject]
            $InputObject,
    
            [Parameter(ParameterSetName='Path', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
            [string[]]
            $Path,
    
            [Parameter(ParameterSetName='LiteralPath', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
            [Alias('PSPath')]
            [string[]]
            $LiteralPath
        )
    
        begin {
            # Determine newline character sequence at the start (might differ across platforms)
            $newLine = [Environment]::NewLine
    
            # Prepare parameter arguments for Add-Content
            $addContentParams = @{ NoNewLine = $true }
            if($PSCmdlet.ParameterSetName -eq 'Path'){
                $addContentParams['Path'] = $Path
            }
            else {
                $addContentParams['LiteralPath'] = $LiteralPath
            }
        }
    
        process {
            # Write to file twice - first a newline, then the content without trailling newline
            Add-Content -Value $newLine @addContentParams
            Add-Content -Value $InputObject @addContentParams
    
            # Write back to pipeline
            Write-Output -InputObject $InputObject
        }
    }
    

    请注意,与Tee-Object 不同,上述函数处于永久“附加模式”。重构它以支持追加和覆盖作为练习留给读者:)

    【讨论】:

    • 现在我们有了一个领先的换行符 ;-) 不是我想要的(我想自己控制写入的数据,尤其是输入的数据,应该输出(未修改)),但是重新实现是一个有效的解决方案,它可以很容易地进行调整。谢谢!