Set-Content在我的文件末尾添加换行符(换行符,CRLF)

时间:2017-07-23 14:53:42

标签: powershell newline powershell-v5.0

我的原始配置文件(web1.config)没有额外的行,当在记事本中查看时(显示所有字符)看起来像:

enter image description here

 <?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.6" />
    <httpRuntime targetFramework="4.6" />
  </system.web>
  <appSettings>
    <add key="myConnectionString" value="server=localhost;database=myDb;uid=myUser;password=myPass;" />
  </appSettings>
</configuration>

现在,我需要应用脚本将我的数据库名称更改为其他类似的内容:

 Move-Item "web1.config" "webtemp.config"
Get-Content "webtemp.config" | ForEach-Object {$_ -replace "database=myDb;", "database=newDb;"} |Set-Content "web1.config" -Force
Remove-Item "webtemp.config"
Write-Output('Settings Changed')

因此,生成的新文件(web1.config)看起来像:

enter image description here

注意文件末尾添加的额外行(完全不需要) 我尝试了所有其他选项,例如: - 使用out-file api - 使用.net IO方法System.IO.StreamWriter - 使用-nonewline标志(它将所有10行转换为单行) - 使用不同的编码选项 - 尝试将\ r \ n替换为\ r \ n(不再作为set-content再次生成crlf)

我使用的是PowerShell v5.1。

3 个答案:

答案 0 :(得分:17)

tl; dr PSv5 + ;请参见旧版本的底部):

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

注意:如果您想要Windows样式的CRLF行结尾而不是Unix样式的LF-only行结尾(PowerShell和许多实用程序可以同时处理),请将"`n"替换为"`r`n"。< / SUP>

PSv5 + 中,Set-Content支持 -NoNewline切换指示Set-Content不要添加换行符(每个输入对象后的换行符。这同样适用于Add-ContentOut-File cmdlet。

换句话说: Set-Content -NoNewline 直接连接 all 其输入对象的字符串表示

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

如果您传递给Set-Content -NoNewline单字符串 已经嵌入了新行,那么您可以按原样使用它并获取期望的结果:

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

请注意Get-Content -Raw整体上读取文件,按原样(除了字符解码)以及?直接出现在{{1}之后的事实意味着该文件没有尾随换行符。

在您的情况下,由于您逐个处理输入行 (通过two 而不是 Get-Content)因此输出数组的行(字符串),您必须首先使用换行符作为分隔符 - 行之间的连接它们只有 - 并将结果传递给-Raw,如顶部所示;这是一个简单的例子:

Set-Content -NoNewline

> ('one', 'two') -join "`n" | Set-Content -NoNewline tmp.txt; "$(Get-Content -Raw tmp.txt)?" one two? 是一个双元素字符串数组,是您逐行处理命令的替代。

编码注释:

在Windows PowerShell中,默认情况下,'one', 'two'根据您系统的传统单字节代码页生成&#34; ANSI&#34; - 编码文件。
要明确控制编码,请使用Set-Content参数。

PSv4 - 中,需要使用.NET Framework的解决方案:

-Encoding

请注意,[System.IO.File]::WriteAllText(),如果没有编码参数,则默认为无BOM的UTF-8。
根据需要将所需的> [System.IO.File]::WriteAllText('tmp.txt', ('one', 'two') -join "`n"); "$(Get-Content -Raw tmp.txt)?" one two? 编码实例作为第三个参数传递。

答案 1 :(得分:2)

我从未注意到这一点,所以我快速搜索并找到了:

set-content adds newlines by default

建议的解决方案是将内容编码为字节,然后将Set-Content与-Encoding参数一起使用。

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

我自己测试过,所以我可以确认这是有效的。

答案 2 :(得分:0)

我看到这是一个 xml 文件。这种方式不会添加换行符。

[xml]$xml = get-content web1.config
$xml.configuration.appSettings.add.value = 
  $xml.configuration.appSettings.add.value -replace 'database=myDb;',
  'database=newDb;'
$xml.save("$pwd\web1.config")  # in case of .net weirdness