【问题标题】:How to expand file content with powershell如何使用powershell扩展文件内容
【发布时间】:2017-03-01 16:26:06
【问题描述】:

我想这样做:

$content = get-content "test.html"
$template = get-content "template.html"
$template | out-file "out.html"

template.html 包含的地方

<html>
  <head>
  </head>
  <body>
    $content
  </body>
</html>

并且 test.html 包含:

<h1>Test Expand</h1>
<div>Hello</div>

我在 out.html 的前 2 个字符中得到了奇怪的字符:

    ��

内容没有展开。

如何解决这个问题?

【问题讨论】:

    标签: powershell variable-expansion file-encodings


    【解决方案1】:

    用以下解决方案补充Mathias R. Jessen's helpful answer

    • 效率更高。
    • 确保输入文件被读取为 UTF-8,即使它们没有(伪)BOM (byte-order mark)
    • 通过编写一个 UTF-8 编码的输出文件没有伪 BOM,完全避免了“奇怪的字符”问题。
    # Explicitly read the input files as UTF-8, as a whole.
    $content =  get-content -raw -encoding utf8 test.html
    $template = get-content -raw -encoding utf8 template.html
    
    # Write to output file using UTF-8 encoding *without a BOM*.
    [IO.File]::WriteAllText(
      "$PWD/out.html",
      $ExecutionContext.InvokeCommand.ExpandString($template)
    )
    
    • get-content -raw (PSv3+) 将作为一个整体中的文件读取到一个单个字符串中(而不是字符串的数组,逐行),虽然更占用内存,但速度更快。对于 HTML 文件,内存使用不应该成为问题。

      • 完整读取文件的另一个优点是,如果模板包含 多行 子表达式 ($(...)),则扩展仍然可以正常工作。
    • get-content -encoding utf8 确保输入文件被解释为使用字符编码 UTF-8,这在当今网络世界中很常见。

      • 这是至关重要的,因为 UTF-8 编码的 HTML 文件通常具有 PowerShell 正确识别文件为 UTF- 所需的 3 字节伪 BOM 8 位编码(见下文)。
    • 然后一个$ExecutionContext.InvokeCommand.ExpandString() 调用就足以执行模板扩展。

    • Out-File -Encoding utf8 总是会使用伪 BOM 创建一个文件,这是不受欢迎的。
      而是使用 [IO.File]::WriteAllText(),利用 .NET Framework默认创建 UTF-8 编码文件BOM.

      • 注意$PWD/out.html 之前的使用,这是确保文件写入PowerShell 的当前位置(目录)所必需的;不幸的是,.NET Framework 认为当前目录与 PowerShell 同步。

    最后,强制性安全警告:仅在您信任的输入上使用此扩展技术,因为可能会执行任意嵌入式命令。


    可选的背景信息

    PowerShell 的Out-File&gt;&gt;&gt; 默认使用UTF-16 LE 字符编码和BOM (byte-order mark)(“奇怪的字符”,如前所述)。

    虽然 Out-File -Encoding utf8 允许创建 UTF-8 输出文件,
    PowerShell总是在输出文件前添加一个 3 字节的 pseudo-BOM,一些实用程序,尤其是那些具有 Unix 传统的实用程序存在问题 - 所以您仍会得到“奇怪的字符”(尽管不同)。

    如果您想要以更类似于 PowerShell 的方式创建无 BOM 的 UTF-8 文件, 请参阅我的 this answer,它定义了一个 Out-FileUtf8NoBom 函数,该函数模拟了 Out-File 的核心功能。

    相反,读取文件时,您必须使用Get-Content -Encoding utf8 来确保无BOM 的UTF-8 文件能够被识别。
    在没有 UTF-8 伪 BOM 的情况下,Get-Content 假定文件使用系统的旧代码页 指定的单字节扩展 ASCII 编码(例如,@ 987654328@ 在英语语言系统上,PowerShell 调用 Default 的编码)。

    请注意,当仅 Windows 的编辑器(例如记事本)创建 UTF-8 文件时,使用伪 BOM(如果您明确选择另存为 UTF-8;默认是传统代码页编码,“ANSI”),越来越流行的跨平台编辑器,例如 Visual Studio CodeAtomSublime Text 默认情况下使用伪 BOM当他们创建文件时。

    【讨论】:

      【解决方案2】:

      对于“奇怪的字符”,它们可能是 BOM(字节顺序标记)。使用Out-File时,用-Encoding参数显式指定输出编码,例如:

      $Template |Out-File out.html -Encoding UTF8
      

      对于字符串扩展,您需要明确告诉 powershell 这样做:

      $Template = $Template |ForEach-Object {
          $ExecutionContext.InvokeCommand.ExpandString($_)
      }
      $Template | Out-File out.html -Encoding UTF8
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-10-05
        • 1970-01-01
        • 2015-05-27
        • 1970-01-01
        • 1970-01-01
        • 2011-06-15
        • 2011-07-29
        相关资源
        最近更新 更多