Dominic Brunetti
Dominic Brunetti

Reputation: 1069

Replacing a block of text in powershell

I have the following (sample) text:

line1
line2
line3

I would like to use the powershell -replace method to replace the whole block with:

lineA
lineB
lineC

I'm not sure how to format this to account for the carriage returns/line breaks... Just encapsulating it in quotes like this doesn't work:

{$_ -replace "line1
line2
line3", 
"lineA
lineB
lineC"}

How would this be achieved? Many thanks!

Upvotes: 1

Views: 3089

Answers (2)

mklement0
mklement0

Reputation: 437109

There is nothing syntactically wrong with your command - it's fine to spread string literals and expressions across multiple lines (but see caveat below), so the problem likely lies elsewhere.


Caveat re line endings:

  • If you use actual line breaks in your string literals, they'll implicitly be encoded based on your script file's line-ending style (CRLF on Windows, LF-only on Unix) - and may not match the line endings in your input.

  • By contrast, if you use control-character escapes `r`n (CRLF) vs. `n` (LF-only) in double-quoted strings, as demonstrated below, you're not only able to represent multiline strings on a single line, but you also make the line-ending style explicit and independent of the script file's own encoding, which is preferable.

In the remainder of this answer I'm assuming that the input has CRLF (Windows-style) line endings; to handle LF-only (Unix-style) input instead, simply replace all `r`n instances with `n.


I suspect that you're not sending your input as a single, multiline string, but line by line, in which case your replacement command will never find a match.

If your input comes from a file, be sure to use Get-Content's -Raw parameter to ensure that the entire file content is sent as a single string, rather than line by line; e.g.:

Get-Content -Raw SomeFile | 
 ForEach-Object { $_ -replace "line1`r`nline2`r`nline3", "lineA`r`nlineB`r`nlineC" }

Alternatively, since you're replacing literals, you can use the [string] type's Replace() method, which operates on literals (which has the advantage of not having to worry about needing to escape regular-expression metacharacters in the replacement string):

Get-Content -Raw SomeFile | 
 ForEach-Object { $_.Replace("line1`r`nline2`r`nline3", "lineA`r`nlineB`r`nlineC") }

MatthewG's answer adds a twist that makes the replacement more robust: appending a final line break to ensure that only a line matching line 3 exactly is considered:
"line1`r`nline2`r`nline3" -> "line1`r`nline2`r`nline3`r`n" and
"lineA`r`nlineB`r`nlineC" -> "lineA`r`nlineB`r`nlineC`r`n"

Upvotes: 2

MatthewG
MatthewG

Reputation: 9283

In Powershell you can use `n (backtick-n) for a newline character.

-replace "line1`nline2`nline3`n", "lineA`nlineB`nlineC`n"

Upvotes: 2

Related Questions