Strings and here document have UNIX line endings on Windows

121 views Asked by At

Both here documents and strings are using UNIX 0x0A line endings on Windows instead of 0x0D0A. How can I get them to be Windows line endings?

PS C:\> $s = @"
>> now
>> is
>> the
>> "@
PS C:\> $s
now
is
the
PS C:\> $s | Format-Hex

   Label: String (System.String) <7B93DCA4>

          Offset Bytes                                           Ascii
                 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
          ------ ----------------------------------------------- -----
0000000000000000 6E 6F 77 0A 69 73 0A 74 68 65                   now�is�the

PS C:\> $s2 = "
>> Now
>> is
>> the
>> "
PS C:\> $s2

Now
is
the

PS C:\> $s2 | Format-Hex

   Label: String (System.String) <33E42D9F>

          Offset Bytes                                           Ascii
                 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
          ------ ----------------------------------------------- -----
0000000000000000 0A 4E 6F 77 0A 69 73 0A 74 68 65 0A             �Now�is�the�

PS C:\> $PSVersionTable.PSVersion.ToString()
7.3.7
3

There are 3 answers

1
zoey-stack-overflow-edition On

You have 2 ways of doing this:

You can use dos2unix.

Or you can use a regex.

There are multiple regex syntaxes but for powershell it is just -replace '(?<!\r)\n', "`r`n"

0
lit On

I am thinking that what is generally the goal is to get the current platform specific newline sequence used. To accomplish this, I think I will use:

-replace '(?<!\r)\n', [Environment]::NewLine

This seems to be working on Windows, wsl, and Ubuntu.

0
mklement0 On

Your own solution is probably the best approach, as it ensures use of the platform-appropriate newline format on all supported platforms.

Let me complement it with background information.

When defining multiline string literals in PowerShell (both regular string literals and their here-string variants):

  • inside a script file (.ps1, .psm1), PowerShell uses the same newline format as the enclosing file.

  • interactively - perhaps surprisingly - PowerShell invariably use LF-only newlines ("`n" in PowerShell), on all supported platforms.

In other words, for use in scripts:

  • If you want either CRLF (Windows-format, "`r`n") or LF-only (Unix-format, "`n") newlines in multiline string literals, save your script file in that format.

  • For cross-platform scripts, use your -replace solution.

    • It will hardly matter in practice, but if you want to avoid unnecessary replacements, you can use the following approach:
      • Save your script with LF-only newlines.

      • Perform a replacement only if necessary, which can then be a literal replacement, via .Replace():

        if ($env:OS -eq 'Windows_NT') { 
          $multiLineStr = $multiLineStr.Replace("`n", "`r`n") 
        }