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

bur*_*rsk 7 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
Run Code Online (Sandbox Code Playgroud)

输入模板:

#!/bin/sh
myvar="<REPLACE_ME>"
echo "my variable: $myvar"
exit 0
Run Code Online (Sandbox Code Playgroud)

导致:

#!/bin/sh myvar="Foo Bar" echo "my variable: $myvar" exit 0
Run Code Online (Sandbox Code Playgroud)

在我看来,某个LF地方被一个简单的空白所取代.最后在脚本的末尾添加了一个CR LF在模板文件中不存在的内容.

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

Tom*_*lak 9

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

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

但实际上你甚至不想将输入分成线条.当Set-ContentOut-File看到数组作为输入时,它们将使用空格连接它.

使用-Rawmake Get-Content将整个文件作为一个字符串返回,这样行结尾(如LFLinux文件)将保持原样.

$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
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

笔记:


Edd*_*mar 7

使用-delimiter "`n" 选项而不是-raw-raw选项将整个内容作为单个字符串读取/返回,尽管它保留换行符,但如果您需要操作内容,例如跳过标题/第一行或跳过空白行等,则它是无用的。

获取内容 - 背景信息:

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

Get-Content $inputFile | Set-Content $outputFilePath 
Run Code Online (Sandbox Code Playgroud)

但是,如果将整个内容(读取)存储到变量(称为 $variable)中,则变量将仅接收单个字符串数组,而没有分隔符/定界符(默认情况下),这意味着您将丢失换行符,但是,当读取文件(使用Get-Content)时,您可以使用该-delimiter选项指定换行符(`n),然后该字符将被保留并写入/存储到 $ 变量中,例如:

Get-Content -Delimiter "`n" $fileToRead
Run Code Online (Sandbox Code Playgroud)

HTH。


Mar*_*agg 5

我认为您需要使用-Raw开关Get-Content来将文件作为单个字符串加载:

[String] $replacement = "Foo Bar"
[String] $template = Get-Content -Path "$pwd\template.sh" -Encoding UTF8 -Raw
$template = $template -replace '<REPLACE_ME>', $replacement
Run Code Online (Sandbox Code Playgroud)

要停止将 Windows 行结尾添加到脚本末尾,我认为您需要使用此 .NET 方法来写入文件:

[io.file]::WriteAllText("$pwd\template.sh",$template)
Run Code Online (Sandbox Code Playgroud)

默认情况下,PowerShell 尝试将文件中每一行的输入转换为字符串数组。我认为由于 Unix 行结尾,它没有成功执行此操作,但随后删除了新行字符。

在 PowerShell 3.0 中,我们现在有了一个新的动态参数 Raw。指定后,Get-Content 将忽略换行符并以一个字符串返回文件的全部内容。Raw 是一个动态参数,仅在文件系统驱动器中可用。