为什么在PowerShell的Get-Content,Regex和Set-Content之后所有新行都消失了?

时间:2017-11-27 13:54:11

标签: powershell newline

我想将文件模板加载到变量中,修改变量中的数据,并将修改后的模板输出到变量的新位置。

问题是PowerShell正在从我的模板中删除换行符。

输入文件(模板文件)具有Unix行结尾,这也是输出所必需的,因为修改版本的接收者是基于Unix的系统。

我有以下代码,结果是连续的单行:

[String] $replacement = "Foo Bar"
[String] $template = Get-Content -Path "$pwd\template.sh" -Encoding UTF8
$template = $template -replace '<REPLACE_ME>', $replacement
$template | Set-Content -Path "$pwd\script.sh" -Encoding UTF8

输入模板:

#!/bin/sh
myvar="<REPLACE_ME>"
echo "my variable: $myvar"
exit 0

导致:

#!/bin/sh myvar="Foo Bar" echo "my variable: $myvar" exit 0

在我看来,某个地方LF被一个简单的空格所取代。最后,在脚本末尾添加了CR LF,模板文件中没有该文件。

如何保留行结尾并防止在最终脚本中添加更多(CR LF错误的行结尾?

3 个答案:

答案 0 :(得分:6)

对于$replacement变量,您实际上不需要指定类型[string],PowerShell会从赋值中推断出来。

对于$template变量,[string]实际上是错误的。默认情况下,Get-Content将为您提供一个字符串数组(即行),而不是一个字符串。

但实际上你甚至不想把输入分成第一行。当Set-ContentOut-File将数组视为输入时,他们会将其与空格连接。

使用-Raw使Get-Content将整个文件作为一个字符串返回,这样行结尾(如Linux文件的LF)将保持原样。

$replacement = "Foo Bar"
$template = Get-Content -Path "$pwd\template.sh" -Encoding UTF8 -Raw
$template = $template -replace '<REPLACE_ME>', $replacement
Set-Content -Path "$pwd\script.sh" -Value $template -Encoding UTF8

PowerShell将使用BOM保存所有UTF-8文件。如果您不想这样,则必须使用其他实用程序来编写文件:

$UTF8_NO_BOM = New-Object System.Text.UTF8Encoding $False

$replacement = "Foo Bar"
$template = Get-Content -Path "$pwd\template.sh" -Encoding UTF8 -Raw
$template = $template -replace '<REPLACE_ME>', $replacement
[System.IO.File]::WriteAllText("$pwd\script.sh", $template, $UTF8_NO_BOM)

注意:

答案 1 :(得分:0)

使用-分隔符“`n” 选项代替 -raw -raw 选项将整个内容读取/返回为单个字符串,尽管它保留换行符,但是如果您需要操纵内容(例如,跳过标题第一行或跳过空白行等。

获取内容-背景信息:

默认情况下,Get-Content cmdlet逐行读取并返回内容,这意味着如果您通过管道传输Set-ContentAdd-Content来立即写每行(正在读取)到输出文件中-换行符将按预期保留并写入,例如:

Get-Content $inputFile | Set-Content $outputFilePath 

但是,如果将整个内容(读取的内容)存储到$ variable中,则会收到一个没有任何分隔符/分隔符的字符串数组(默认情况下),这意味着您会丢失换行符,但是,读取文件(使用Get-Content)时,您可以使用-delimiter选项指定换行符,例如:

Get-Content -Delimiter "`n" $fileToRead

HTH。

答案 2 :(得分:0)

我使用的是Get-Content-Tail,它不允许您同时指定-Raw,但是我对Out-String确实很幸运。因此,就您而言:

$template = Out-String -InputObject $( Get-Content -Path "$pwd\template.sh" -Encoding UTF8 -Raw)

或者也许,如果您关心尾巴:

$template = Out-String -InputObject $(Get-Content -Path "$pwd\template.sh" -tail 4)