1

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!

Dominic Brunetti
  • 989
  • 3
  • 18
  • 36

2 Answers2

2

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

-replace "line1`nline2`nline3`n", "lineA`nlineB`nlineC`n"
MatthewG
  • 8,583
  • 2
  • 25
  • 27
  • `\`n` (LF-only, Unix) and `\`r\`n` (CRLF, Windows) are indeed helpful for (a) single-line representations of multiline strings, and (b) explicitly controlling the line ending style. However, note that unless switching to a _different_ line ending style is required, your command is (essentially) _equivalent_ to the OP's (and therefore doesn't solve the problem). Kudos for adding a terminating line break to make the replacement more robust. – mklement0 Oct 20 '16 at 20:23
2

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"

Community
  • 1
  • 1
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • the -raw parameter did it! So much to learn. :) Thank you so much!!! – Dominic Brunetti Oct 20 '16 at 19:56
  • @DominicBrunetti: My pleasure; generally, PowerShell sends _collections_ through the pipeline, and in the case of text files, it is a collection of _lines_, so they are sent one by one. Generally, that's preferable, but in this case you do need the whole contents at once. Please also note the caveat re line endings I've just added. – mklement0 Oct 20 '16 at 20:03
  • Got it, makes sense. I really appreciate the help and explanation. – Dominic Brunetti Oct 20 '16 at 20:11
  • 1
    side effect is this is much faster (I'm working with very large files) as it doesn't have to iterate line by line. – Dominic Brunetti Oct 20 '16 at 20:26
  • @DominicBrunetti: Glad to hear it, but note the down-side: the entire file must fit into memory as a whole (sounds like you have enough memory, fortunately). – mklement0 Oct 20 '16 at 20:27
  • My work laptop (8GB) choked right away - LOL. Ran on workstation (32GB) and no problem. Thanks again. – Dominic Brunetti Oct 20 '16 at 22:43