防止在 PowerShell Out-File 命令中尾随换行符

Prevent trailing newline in PowerShell Out-File command

如何防止 PowerShell 的 Out-File 命令在其输出的文本后附加换行符?

例如,运行 下面的命令生成一个包含内容 "TestTest\r\n" 而不仅仅是 "TestTest".

的文件
"TestTest" | Out-File -encoding ascii test.txt

在 PowerShell 5.0+ 中,您将使用:

"TestTest" | Out-File -encoding ascii test.txt -NoNewline

但在早期版本中,您根本无法使用该 cmdlet。

试试这个:

[System.IO.File]::WriteAllText($FilePath,"TestTest",[System.Text.Encoding]::ASCII)

补充-NoNewline:

以下不仅适用于 Out-File,也适用于 Set-Content / Add-Content;如前所述,-NoNewline 需要 PSv5+。

注意-NoNewline表示用多个对象输出,不仅 trailing 换行符(换行符)被抑制,而且 any 换行符。

换句话说:输入对象的字符串表示直接连接,没有分隔符(终止符)

因此,以下命令产生相同的文件内容(TestTest 没有尾随换行符):

# Single input string
"TestTest" | Out-File -encoding ascii test.txt -NoNewline

# Equivalent command: 2-element array of strings that are directly concatenated.
"Test", "Test" | Out-File -encoding ascii test.txt -NoNewline

为了 仅在 之间放置换行符,而不 输出对象之后, 您必须 明确地用换行符加入对象:

"Test", "Test" -join [Environment]::NewLine |
  Out-File -encoding ascii test.txt -NoNewline

[Environment]::NewLine 是适合平台的换行符序列(在 Windows 上是 CRLF,在类 Unix 平台上是 LF);如果需要,您还可以使用 "`r`n""`n"

显式生成任一序列

警告:

上述 -join 解决方案隐式地将输入对象转换为字符串(如果它们尚未转换),并且通过对每个对象调用 .NET .ToString() 方法来实现。这通常会产生与 Out-File 直接创建的表示不同的表示,因为 Out-File 使用 PowerShell 的 默认输出格式化程序 ;例如,比较 (Get-Date).ToString()Get-Date.

的输出

如果您的输入仅包含字符串 and/or 非字符串,其 .ToString() 表示令人满意,上述解决方案有效,但请注意它是通常最好使用 Set-Content cmdlet,它隐含地应用相同的字符串化。
有关 Out-FileSet-Content 之间差异的完整讨论,请参阅我的 this answer

如果您的输入有非字符串,您希望按照它们打印到控制台的方式进行格式化,实际上没有简单的解决方案:虽然您可以使用 Out-String 创建每个对象的字符串表示使用默认格式化程序,Out-String 缺少 -NoNewline(从 v5.1 开始;this GitHub issue 建议引入它)总是会产生尾随换行符。

为了补充 briantist 和 mklement0 的有用答案 -NoNewline:

我创建了这个小函数来替换以前版本的 powershell 中 Out-File-NoNewLine 参数。

注意:在我的例子中,它是一个包含 7 行的 .csv 文件(星期几和更多值)

## Receive the value we want to add and "yes" or "no" depending on whether we want to 
put the value on a new line or not.
function AddValueToLogFile ($value, $NewLine) {
    ## If the log file exists:
    if (Test-path $Config.LogPath) {
        ## And we don't want to add a new line, the value is concatenated at the end.
        if ($NewLine -eq "no") {
            $file = Get-Content -Path $Config.LogPath 
            ## If the file has more than one line
            if ($file -is [array]) {
                $file[-1]+= ";" + $value
            }
            ## if the file only has one line
            else {
                $file +=  ";" + $value
            }
            $file | Out-File -FilePath $Config.LogPath
        }
        ## If we want to insert a new line the append parameter is used.
        elseif ($NewLine -eq "yes") {
            $value | Out-File -Append -FilePath $Config.LogPath
        }
    }
    ## If the log file does not exist it is passed as a value
    elseif (!(Test-path $Config.LogPath)) {
        $value | Out-File -FilePath $Config.LogPath
    }
}