Steve A
Steve A

Reputation: 2013

Replacing/inserting newlines using Powershell

(I have read the other threads with similar names...)

I'm new to PowerShell. I am trying to understand how to find and replace newlines. For example, find double newlines and replace them with a single or vice versa.

I have a test document that was created using Notepad:

The quick brown fox jumped over the lazy dog
The quick brown fox jumped over the lazy dog

The quick brown fox jumped over the lazy dog
The quick brown fox jumped over the lazy dog

I am working in the PowerShell ISE for testing/learning.

When I run the following command (attempting to replace one newline with two):

((Get-Content -path $filename -raw) -replace '`n','`n`n') | Set-Content -path $filename
Get-Content -path $filename -raw

The output is unchanged. So I tried the following and it remained unchanged.

((Get-Content -path $filename -raw) -replace '`r`n','`r`n`r`n') | Set-Content -path $filename

So, knowing that PowerShell uses a back-tick rather than a backslash, but out of frustration, I tried the following command:

((Get-Content -path $filename -raw) -replace '\n','\n\n') | Set-Content -path $filename

And, surprisingly (to me), all of the newlines were replaced, but with the string literal '\n\n'. So it seems searching for a newline worked with a backslash but not with a back-tick. The replacement, unfortunately, was the literal string rather than the CRLF I need.

I'm stumped. But for what it's worth, I also tried the following and the string literal was again used for the replacement (i.e., in place of newlines, the document contained '`r`n').

((Get-Content -path $filename -raw) -replace '\n','`r`n') | Set-Content -path $filename

I have seen many posts where people were mistakenly using a backslash, but in my case it seems like a backslash is required for the search, and I don't understand what is required to replace a newline.

Thanks!

Upvotes: 0

Views: 2507

Answers (3)

js2010
js2010

Reputation: 27443

Use double quotes. You probably also want the -nonewline option to set-content, so that another `r`n doesn't get put at the end of the file.

PS> '`n'
`n
PS> "`n"



PS> (Get-Content -path $filename -raw) -replace "`n","`n`n" | 
      Set-Content -path $filename -nonewline

Upvotes: 1

Theo
Theo

Reputation: 61068

There are several ways of doing this. First one is to read the file as a single string and perform a regex -replace on it: Remember that on Windows machines the Newline is a combination of two characters CR ('\r', ASCII value 13) and LF ('\n', ASCII value 10).

$filename = 'D:\test.txt'

# replace single newlines by a double newline
$replaceWith = '{0}{0}' -f [Environment]::NewLine
(Get-Content -Path $filename -Raw) -replace '\r?\n', $replaceWith | Set-Content -Path 'D:\test-to-double.txt' -Force

# replace double newlines by a single newline
$replaceWith = [Environment]::NewLine
(Get-Content -Path $filename -Raw) -replace '(\r?\n){2}', $replaceWith | Set-Content -Path 'D:\test-to-single.txt' -Force

Another way is to read in the file as string array (let PowerShell deal with single newlines):

# read the file as string array and join the elements with a double newline
$replaceWith = '{0}{0}' -f [Environment]::NewLine
(Get-Content -Path $filename) -join $replaceWith | Set-Content -Path 'D:\test-to-double.txt' -Force

# read the file as string array and join the elements with a single newline
$replaceWith = [Environment]::NewLine
(Get-Content -Path $filename) -join $replaceWith | Set-Content -Path 'D:\test-to-single.txt' -Force

The latter method is also extremely suited for removing empty or whitespace-only lines before you 'normalize' the newlines in the text: In that case, just replace (Get-Content -Path $filename) with (Get-Content -Path $filename | Where-Object { $_ -match '\S' })

Upvotes: 1

Adam
Adam

Reputation: 4168

'`n' just matches the literal characters [backtick][n], which isn't what you want. You want to interpret those values. For that, you'll need to use double quotes i.e., '`n' should be "`n". According to Microsoft...

The special characters in PowerShell begin with the backtick character, also known as the grave accent (ASCII 96). ... These characters are case-sensitive. The escape character is only interpreted when used within double quoted (") strings.

Upvotes: 3

Related Questions