【问题标题】:How to get actual separate lines in PowerShell's Write-Output using a newline character如何使用换行符在 PowerShell 的 Write-Output 中获取实际的单独行
【发布时间】:2022-01-26 09:04:33
【问题描述】:

我尝试创建一个多行输入来练习Select-String,希望只输出一个匹配的行,就像我通常会在echo -e ... | grep 组合中看到它一样。但是下面的命令仍然给了我这两行。似乎换行符仅在最终输出上解释,Select-String 仍然得到单行输入

Write-Output "Hi`nthere" | Select-String -Pattern "i"
#
# Hi
# there
#
#

虽然我希望它只会返回

Hi

我使用了这个版本的 PowerShell:

Get-Host | Select-Object Version
# 5.1.19041.906

bash 相比,我将执行以下操作来测试 bash 中多行输入的命令。我通常使用echo -e 生成多行,然后grep 处理各个行。

echo -e "Hi\nthere" | grep "i"
# Hi

我希望有人能解释一下我在 PowerShell 中错过了什么?这个问题对我来说似乎是一个基本的误解,我也不确定 Google 是为了什么。

编辑

[edit 1]:问题也适用于以回车符结尾的行

Write-Output "Hi`r`nthere" | Select-String -Pattern "i"

我看到用逗号分隔可以作为有效的多行输入。所以也许问题是如何从换行转换为实际的输入行分隔。

Write-Output "Hi","there" | Select-String -Pattern "i"
# Hi

[edit 2]:edit 1 我找到了this stackoverflow-answer,现在对我来说它可以在哪里使用

Write-Output "Hi`nthere".Split([Environment]::NewLine) | Select-String -Pattern "i"
# or
Write-Output "Hi`nthere".Split("`n") | Select-String -Pattern "i"

仍然有人可以解释为什么这与此处相关,但在bash 中不相关?

【问题讨论】:

  • echo -e … in bash: -e 表示启用some backslash-escaped characters的解释。 PowerShell 等效项(大致不完整):Write-Output ("Hi`nthere" -split "`r|`n") | Select-String -Pattern "i"
  • Select-String operates on its input objects individually,这意味着您需要首先使用(("Hi`nthere" -split '\r?\n') | Select-String -Pattern "i").Line 将多行字符串拆分为单独的行。解释见this answer
  • 感谢@JosefZ 和@Theo,尤其是@JosefZ 向我指出“-e”的详细解释,这似乎是我正在寻找的实际解释。所以 bash 中的 -e 等价于 -split "`r|`\n")
  • 重新考虑这个...我实际上更喜欢`-split "`r?`n"

标签: bash powershell grep select-string


【解决方案1】:

所有信息都在cmets中,但让我总结和补充一下:

PowerShell 的管道是基于对象的,Select-String 对每个输入对象进行操作 - 即使它恰好是一个单个多行字符串对象,比如Write-Output "Hi`nthere"的输出

  • 只有外部程序的输出逐行流式传输。

因此,您必须将多行字符串拆分为单独的行,以便将它们单独匹配。

最好的习惯用法是-split '\r?\n',因为它可以识别 Windows 格式的 CRLF 和 Unix 格式的 LF-only 换行符:

"Hi`nthere" -split '\r?\n' | Select-String -Pattern "i"

注意:

  • 我省略了Write-Output 以支持PowerShell 的隐式 输出行为(有关更多信息,请参阅this answer 的底部部分)。

  • 有关-split '\r?\n' 工作原理的更多信息,请参阅this answer

  • Select-String直接输出匹配的行(字符串);相反,它将它们包装在match-information objects 中,提供有关每个匹配项的元数据。只获取匹配的行(字符串):

    • PowerShell (Core) 7+ 中,添加 -Raw 开关。
    • Windows PowerShell 中,通过管道传送到 ForEach-Object Line 或将整个调用包装在 (...).Line

【讨论】:

    猜你喜欢
    • 2021-03-02
    • 1970-01-01
    • 2020-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多