Home > Back-end >  How to get actual separate lines in PowerShell's Write-Output using a newline character
How to get actual separate lines in PowerShell's Write-Output using a newline character

Time:12-28

I tried to create a multiline Input to practice Select-String, expecting only a single matching line to be output, like I would normaly see it in an echo -e ... | grep combination. But the following command still gives me both lines. It seems to be the newline is only interpreted on final ouptut and Select-String still gets a single line of input

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

while I would expect it to return just

Hi

I used this version of PowerShell:

Get-Host | Select-Object Version
# 5.1.19041.906

Comparing with bash I would do the following for testing commands on multiline input in bash. I usually generate multiple lines with echo -e and then grep processes the individual lines.

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

I hope someone can explain what I miss here in PowerShell? This problem seems like a basic misconception to me, where I also was not sure what to Google for.

Edits

[edit 1]: problem also for line ending with carriage return

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

I saw that separating with commas works as valid multiline input. So maybe the question is how to convert from newline to actual input line separation.

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

[edit 2]: from edit 1 I found this stackoverflow-answer, where for me it now works with

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

Still may someone please explain why this is relevant here, but not in bash?

CodePudding user response:

All the information is in the comments, but let me summarize and complement it:

PowerShell's pipeline is object-based, and Select-String operates on each input object - even if that happens to be a single multi-line string object, such as output by Write-Output "Hi`nthere"

  • It is only the output from external programs that is streamed line by line.

Therefore, you must split your multi-line string into individual lines in order to match them as such.

The best idiom for that is -split '\r?\n', because it recognizes both Windows-format CRLF and Unix-format LF-only newlines :

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

Note:

  • I've omitted Write-Output in favor of PowerShell's implicit output behavior (see the bottom section of this answer for more information).

  • For more information on how -split '\r?\n' works, see this answer.

  • Select-String doesn't directly output the matching lines (strings); instead it wraps them in match-information objects that provide metadata about each match. To get just the matching line (string):

    • In PowerShell (Core) 7 , add the -Raw switch.
    • In Windows PowerShell, pipe to ForEach-Object Line or wrap the entire call in (...).Line
  • Related