代码之家  ›  专栏  ›  技术社区  ›  burnersk

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

  •  25
  • burnersk  · 技术社区  · 7 年前

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

    问题是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 ) 错误的 最终脚本的行尾?

    4 回复  |  直到 6 年前
        1
  •  32
  •   Peter Mortensen icecrime    6 年前

    对于 $replacement 变量,您实际上不需要指定类型 [string] ,PowerShell将从分配中推断。

    对于 $template 变量 [字符串] Get-Content 将为您提供一个字符串数组(即行),而不是一个字符串。

    但事实上,你甚至不想把输入分成几行。什么时候 Set-Content Out-File 将数组视为输入,它们将用空格连接。

    使用 -Raw 制造 获取内容 将整个文件作为一个字符串返回,这样也可以返回行结尾(如 LF 对于Linux文件),将保持不变。

    $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 . 如果不希望这样,则必须使用其他实用程序来写入文件:

    $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)
    

    笔记:

        2
  •  3
  •   Mark Wragg    7 年前

    我认为你需要使用 -Raw 切换为 Get-Content 为了将文件作为单个字符串加载:

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

    为了阻止Windows行尾被添加到脚本的末尾,我认为您需要使用这个。NET写入文件的方法:

    [io.file]::WriteAllText("$pwd\template.sh",$template)
    

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

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

        3
  •  2
  •   Eddie Kumar    5 年前

    使用 -分隔符“`n” 选项而不是 -生的 . 这个 -生的 选项以单个字符串的形式读取/返回整个内容,尽管它保留了新行字符,但如果您需要操作内容(例如跳过标题/第1行或跳过空行等),则该选项无效。

    获取内容-背景信息:

    默认情况下 Get-Content cmdlet读取(&W);逐行返回内容,这意味着如果您对 Set-Content Add-Content 要立即将每一行(正在读取)写入输出文件,换行符将按预期进行保存和写入,例如:

    Get-Content $inputFile | Set-Content $outputFilePath 
    

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

    Get-Content -Delimiter "`n" $fileToRead
    

    HTH。

        4
  •  0
  •   Jeremy Caney Abloin    4 年前

    我正在使用 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)