Set-Content appends a newline (line break, CRLF) at the end of my file

后端 未结 2 605
情书的邮戳
情书的邮戳 2020-11-28 12:41

My original config file (web1.config) has no extra line and when viewed in notepad (showing all characters) looks as:

          


        
相关标签:
2条回答
  • 2020-11-28 13:00

    I never noticed this, so i did a quick search and found:

    set-content adds newlines by default

    The suggested solution is to encode your content to bytes and then use Set-Content with the -Encoding parameter.

    Set-Content test.txt ([byte[]][char[]] "test") -Encoding Byte
    

    I tested it myself so i can confirm that this works.

    0 讨论(0)
  • 2020-11-28 13:07

    tl;dr (PSv5+; see bottom for older versions):

    (Get-Content webtemp.config) -replace "database=myDb;","database=newDb;" -join "`n" |
      Set-Content -NoNewline -Force web1.config
    

    Note: Replace "`n" with "`r`n" if you want Windows-style CRLF line endings rather than Unix-style LF-only line endings (PowerShell and many utilities can handle both).


    In PSv5+, Set-Content supports the -NoNewline switch, which instructs Set-Content not to add a newline (line break) after each input object. The same applies analogously to the Add-Content and Out-File cmdlets.

    In other words: Set-Content -NoNewline directly concatenates the string representations of all its input objects:

    > 'one', 'two' | Set-Content -NoNewline tmp.txt; Get-Content tmp.txt
    onetwo
    

    If what you're passing to Set-Content -NoNewline is a single string that already has embedded newlines, you can use it as-is and get the desired result:

    > "one`ntwo" | Set-Content -NoNewline tmp.txt; "$(Get-Content -Raw tmp.txt)?"
    one
    two?
    

    Note that Get-Content -Raw reads the file as a whole, as-is (aside from character decoding) and the fact that the ? appears directly after two implies that the file has no trailing newline.

    In your case, since you're processing input lines one by one (via Get-Content without -Raw) and therefore outputting an array of lines (strings), you must first join them with a newline as the separator - between lines only - and pass the result to Set-Content -NoNewline, as shown at the top; here's a simplified example:

    > ('one', 'two') -join "`n" | Set-Content -NoNewline tmp.txt; "$(Get-Content -Raw tmp.txt)?"
    one
    two?
    

    'one', 'two' is a two-element string array that is a stand-in for your line-by-line processing command.

    Encoding note:

    In Windows PowerShell, Set-Content produces "ANSI"-encoded files by default, based on your system's legacy, single-byte code page.
    To control the encoding explicitly, use the -Encoding parameter.


    In PSv4-, a solution that uses the .NET Framework is needed:

    > [System.IO.File]::WriteAllText('tmp.txt', ('one', 'two') -join "`n"); "$(Get-Content -Raw tmp.txt)?"
    one
    two?
    

    Note that [System.IO.File]::WriteAllText(), in the absence of an encoding argument, defaults to BOM-less UTF-8.
    Pass the desired [System.Text.Encoding] encoding instance as the 3rd argument as needed.

    0 讨论(0)
提交回复
热议问题