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!

3
  • What is the source of $_ here? Is it really a multiline string, such as what you'd get with Get-Content -Raw? Commented Oct 20, 2016 at 19:32
  • yes, they are distinct lines in a file. Commented Oct 20, 2016 at 19:32
  • 2
    In a regex pattern, you may use (?:\r?\n|\r) to denote a single line break of the most common types. Inside the replacement, use "`r`n" or similar to denote a regular linebreak sequence/symbol. Commented Oct 20, 2016 at 19:45

2 Answers 2

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"

Sign up to request clarification or add additional context in comments.

6 Comments

the -raw parameter did it! So much to learn. :) Thank you so much!!!
@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.
Got it, makes sense. I really appreciate the help and explanation.
side effect is this is much faster (I'm working with very large files) as it doesn't have to iterate line by line.
@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).
|
2

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

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

1 Comment

`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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.