'PowerShell - Inserting newline char in string during regex replace

I'm trying to search a string for some numbers and insert a new line before each, not including the first one.

I don't seem to be able to use the traditional regex \n char to insert a newline. If I use the PowerShell escape character, the regex variable from the set is ignored.

For a given source string of

$theString = "1. First line 2. Second line 3. Third line"

What I want is:

1. First Line
2. Second Line
3. Third line

So I tried this regex to find the numbers 2 to 9 followed by a period and a space:

$theString = $theString -replace '([2-9]\. )','\n$1'

but that yields:

1. First line\n2. Second line\n3. Third line

So I tried using the PowerShell escape character for a newline and put it inside double inverted commas:

$theString = $theString -replace '([2-9]\. )',"`n$1"

but that yields:

1. First Line
Second Line
Third line

I tried using \r, \r\n, \`r, \`r\`n, etc. trying to force the linebreak, but can't get it to happen without losing the ability to include the current regex variable.



Solution 1:[1]

The problem is caused as $ is used both for ordinary Powershell variables and capture groups. In order to process it as a capture group identifier, single quotes ' are needed. But single quote tells Powershell not to interpret the newline escape as a newline but literal `n.

Catenating two differently quoted strings does the trick. Like so,

$theString -replace '([2-9]\. )', $("`n"+'$1')
1. First line
2. Second line
3. Third line

As an alternative, use double quotes " and escape the dollar. Like so,

$theString -replace '([2-9]\. )', "`n`$1"
1. First line
2. Second line
3. Third line

Yet another an alternative (thanks to Lieven) uses here-strings. A here-string contains a newline. Maybe a variable makes it easier to use. Like so,

$repl = @'

$1
'@

$theString -replace '([2-9]\. )', $repl
1. First line
2. Second line
3. Third line

Solution 2:[2]

To allow any number I'd replace the leading space with a newline and use a positive look ahead to filter on.

$theString = "1. First line 2. Second line 3. Third line 11. Eleventh line"
$thestring  -replace ' (?=[1-9]+\. )', "`n"

Sample output:

1. First line
2. Second line
3. Third line
11. Eleventh line

To have an array of strings output, with the same RegEx:

$thestring -split ' (?=[1-9]+\. )'

Solution 3:[3]

Another solution would be:

$theString = "1. First line 2. Second line 3. Third line"
$theString -replace '(\s)([0-9]+\.)',([System.Environment]::NewLine+'$2')

which is actually pretty similar to your second line of code.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Lieven Keersmaekers
Solution 2
Solution 3 TobyU