【问题标题】:Avoiding newline in write-output避免写输出中的换行符
【发布时间】:2020-03-18 09:32:42
【问题描述】:

我想在日志文件中收集脚本的所有输出,并且必须使用 write-output 代替 write-host。

Write-Output "Server:" $a 看起来像

Server:
foo
.

我真的必须写信吗
write-output $("sfdghk:" + $a) 得到Server:Foo

谢谢 -jt

【问题讨论】:

  • Write-Output "Server:$a"
  • @empo:您应该将此作为答案提交。在我看来,它比迄今为止唯一的答案更直接和相关。

标签: powershell


【解决方案1】:

在互联网某处找到:

Write-Output "Server: $($a)"

在我的代码中效果很好。

【讨论】:

  • 对于这个例子,$(...) 结构是多余的,因为它表示将括号内的所有内容视为脚本而不是文本。由于 $a 已被解释并插入到带引号的字符串中,因此不需要添加包装器。 Write-Output "Server: $a" ...可以正常工作。当您尝试访问变量的方法或属性时,请使用包装器 $()$a = "I like eggs." Write-Output "Character count: $($a.length)" 将在没有 $(...) 包装器的情况下打印出 I like eggs..length
  • 谢谢你,你帮我省了一天!我认为这是 powershell 设计问题,它不应该使方式与另一个脚本语言如此不同。
【解决方案2】:

9 小时...我开始回答。

在 Powershell 中,您操作的一切都是对象。

所以 "Server:" 是一个对象,$a 是一个对象

PS> "server :".gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

Write-output 是一个 CmdLet,它将对象放入一种列表(管道)中,以供其他 CmdLet 或脚本使用。所以“Server:”和“foo”之间没有真正的换行符。这是控制台向您显示对象列表(数组)的方式。正如您在此处看到的:

PS> $a = "foo"
PS> (Write-Output "Server :" $a).gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

这里明明是一个摘要,但希望能让你明白。

【讨论】:

    【解决方案3】:
    Write-Output "Server: $a"
    Write-Output ("Server: {0}" -f $a)
    Write-Output ("Server: " + $a)
    

    如果要将脚本的输出收集到日志文件中,请考虑使用Start-Transcript。它将每个命令和所有 PowerShell 输出记录到一个文件中。但是,它不会记录发送到标准输出的任何内容,因此如果您使用任何旧命令,则必须将它们的输出通过管道传输到 Write-Host

    Start-Transcript C:\logs\mylog.txt
    Write-Host "Server: " $a
    ping | Write-Host
    

    【讨论】:

    • PowerShell 的 等效 到 stdout 是它的 成功输出流 并且发送到那里 do 的内容会被记录。 Write-Host过去没有写入stdout而是直接打印到控制台,这就是为什么没有显示这样的输出在成绩单中。然而,在 PSv5+ 中,Write-Host / Out-Host 现在写入新引入的信息流(新的Write-Information cmdlet 也是如此),现在确实被记录了.您可以使用$null = ... 完全抑制输出,或者在这种情况下模拟PSv4-Write-Host 行为,使用$host.ui.WriteLine()
    【解决方案4】:

    现有答案中有很好的信息,但让我尝试一个务实的总结:

    • 当打印到控制台重定向到文件时,Write-Output用换行符分隔多个参数每个

    • 因此,为了产生单行输出,您必须将要输出的部分“预组装”成单行字符串你作为 single 参数传递。

    • 除了禁止枚举集合,您通常不需要显式使用Write-Output,因为 PowerShell默认情况下发送任何未在一个变量或重定向到别处或通过管道发送到 [success] 输出流Write-Output 也写入);因此,在手头的情况下,以下内容就足够了:

    "Server: $a"  # what this expandable string expands to is *implicitly* output
    

    可能令人困惑的是 Write-Host cmdlet 的作用不同,但重要的是要注意它有一个不同的目的

    # IMPORTANT: Do not use Write-Host to output *data*; only use it to write
    #            directly to the host (console).
    PS> Write-Host "Server:"     $a    # multiple spaces used on purpose
    Server: srv1
    

    Write-HostWrite-Output 不同,多个参数由 单个空格 分隔。
    还有其他重要的区别,总结在我的this answer


    鉴于问题的通用标题,让我们也解决如何抑制尾随换行符

    • 对于打印到控制台,您可以使用Write-Host -NoNewline

    • 使用 data 输出,无论是通过Write-Output、隐式输出还是来自其他命令:

      • 当输出发送到控制台时,您无法阻止尾随换行符。

      • 很遗憾,从 Windows PowerShell v5.1 / PowerShell Core v6.0.0 开始,您无法在向外部发送文本时阻止尾随换行符通过管道的程序 - 请参阅this GitHub issue

      • 然而,在 PSv5+ 中,您可以文件中捕获输出时防止尾随换行符,通过使用Out-File -NoNewlineSet-Content -NoNewline(在PSv4-中,必须直接使用.NET Framework);相比之下,使用> 重定向到文件确实会附加一个尾随换行符。

        • 警告:如果您要输出 多个 对象,-NoNewline 不仅会抑制 尾随 换行符,还会抑制这些对象之间的换行符 .
        • 关于Out-FileSet-Content 之间的区别以及何时选择哪个,请参阅我的this answer

    【讨论】:

    • 如果您需要使用args[n],则不能使用"$args[-1]",而必须使用格式化的形式,例如:Write-Output ("{0} `t{1}" -f $args[-1],$PWD) | Out-File -Append $HOME/.somefile
    • @not2qubit:作为一个独立的命令参数,您可以按原样使用$args[-1]& { Write-Output $args[-1] } one two。要将其嵌入到更大的字符串中,您需要 $(...): & { Write-Output "$($args[-1])!" } one two - 请参阅 PowerShell 的 string interpolation rules
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-06
    • 1970-01-01
    • 1970-01-01
    • 2022-08-20
    • 2012-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多