【问题标题】:How to properly escape quotes in powershell v2?如何在 powershell v2 中正确转义引号?
【发布时间】:2022-01-19 02:24:25
【问题描述】:

如何正确转义 powershell v2 中的引号(从批处理文件中调用)?

我试过了:

powershell -Command "(gc file1.txt) -join "`n" | Out-File file2.txt"

powershell -Command "(gc file1.txt) -join ""`n"" | Out-File file2.txt"

powershell -Command "(gc file1.txt) -join '"`n`" | Out-File file2.txt"

但他们都失败了。

编者注:该命令的目的是将 Windows CRLF 换行符转换为 Unix LF-only 换行符,以便创建将在 Linux 上处理的文件。支持>

【问题讨论】:

  • 不要停留在两个引号,使用三个"""`n""",你就会成功!
  • 更重要的是,PowerShell 中的 backtick-n 被记录为在 Windows 中扩展为 CR/LF,这有点适合练习。如果查询者真的希望用only LF 分隔行,他应该使用[char]10 作为连接字符。 (以及如何在 cmets 中将 backtick-n 转换为“输入”文本?)
  • @JeffZeitlin 呃哦……我发现的所有例子都声称 `n 只是一个 LF。
  • @RockPaperLizard - 虽然Get-Help about_Special_Characters 确实调用`n“换行”,但它说它插入了一个“换行符”,如果你对结果运行十六进制转储,你会见0D 0A
  • "`n"总是只是 LF(带有 Unicode 代码点 10 (0xA) 的 单个 字符),如以下返回 $True 的语句所示:"`n".length -eq 1[char] 10 -eq [char] "`n"。不幸的是,Get-Help about_Special_Characters 并没有明确说明这一点:它提到了“换行符”和“换行符”,而没有提到代表什么特定字符 [序列]。 (在 PowerShell 中,LF 本身与 CRLF 一样是有效的换行符)。

标签: powershell batch-file windows-7 escaping powershell-2.0


【解决方案1】:

从批处理文件 (cmd.exe),您必须 \-escape 嵌入 " 实例 (尽管 PowerShell-在内部它是 `(反引号)用作转义字符):

正如wOxxOm 在对该问题的评论中指出的那样,在Windows PowerShell 使用""" 嵌入单个" 也是一种选择。 但是,鉴于大多数命令行实用程序都支持\"\" 更容易记住。但是,"""\" 都可以在cmd.exe 一侧中断,在这种情况下需要 "^"" (原文如此) (@987654339 @ in PowerShell (Core) 7+).

powershell -Command "(gc file1.txt) -join \"`n\" | Set-Content -NoNewLine file2.txt"

注意:

  • Set-Content -NoNewline 需要 PSv5+

  • Set-Content 默认写入“ANSI”编码文件(例如,基于美国英语系统上的代码页 Windows-1252);使用-Encoding 参数来改变它。

    • 由于您只处理 字符串Set-ContentOut-File 更可取,只有在您有必须首先应用 PowerShell 的默认格式的非字符串对象时才需要它.
  • 考虑使用powershell -NoProfile ... 来禁止加载 PowerShell 的配置文件,以加快执行速度和更可预测的执行环境。


PSv2 解决方案:

很遗憾,在 PSv5 之前,只有 Write-Host cmdlet 支持 -NoNewline 参数(v2 中引入),在这里没有任何帮助,所以必须使用 .NET 框架:

powershell -Command "[IO.File]::WriteAllText(\"$PWD/file2.txt\", ((gc $PWD/file1.txt) -join \"`n\") + \"`n\")"

注意需要明确使用路径前缀 $PWD,因为 .NET Framework 的当前目录通常与 PowerShell 的不同。

此外,输出文件的编码将是 UTF-8,没有 BOM,但您可以将不同的编码作为第三个参数传递给 [IO.File]::WriteAllText(),例如 [System.Text.Encoding]::Default 以匹配 @ 987654353@ 的默认行为(从 Windows PowerShell v5.1 开始)。


可选阅读:特定于平台的换行符"`n" vs. "`r`n" vs. [Environment]::Newline

隐式选择换行符(换行符):

  • 读取时,PowerShell 只接受 LF(Unix 风格)和 CRLF(Windows 风格)换行符(换行符)可互换

  • 写入时(例如,将数组行/对象发送到带有>/Out-File/Set-Content的文件时,PowerShell使用适合平台的换行序列。
    但是请注意,给定 string 输入对象中嵌入 的任何换行符序列都将按原样发送到文件。

至于转义序列/常量

  • [Environment]::Newline 包含适合平台的换行符。

  • "`n"总是只是 LF (\n)

    • 正如 "`n".Length 返回 1[char] 10 -eq [char] "`n" 返回 $True 所证明的那样(10 是 LF 的十进制 Unicode/ASCII 代码点)。

    • 文档没有明确说明这一点:Get-Help about_Special_Characters 提到了“换行符”和“换行符”,但没有提到具体的字符 [sequence] 代表什么。 (如前所述,LF 本身与 PowerShell 中的 CRLF 一样有效的换行符。

  • 因此,要创建 CRLF 序列,您必须使用"`r`n"

  • 如果您需要匹配 either 格式的换行符,可以使用regex '\r?\n',与-match-replace 等运算符一起使用-split

至于多行字符串字面量在脚本(包括here-documents):

  • 它们反映了源文件的换行样式。也就是说,如果您的脚本使用 CRLF 换行符,那么嵌入在多行字符串中的换行符也是如此。

【讨论】:

    【解决方案2】:

    这是从 PowerShell 命令行执行此操作的一种方法:

    (Get-Content Input.txt -Raw) -replace "`r`n","`n" | Out-File Output.txt -Encoding ASCII -NoNewline
    

    正如其他人所指出的,这是一个 PowerShell v5 解决方案(-Raw 出现在 v3 中,-NoNewline 出现在 v5 中)。

    这是同一事物的 PowerShell v2 版本:

    $content = [IO.File]::ReadAllText("C:\Path\Input.txt") -replace "`r`n","`n"
    [IO.File]::WriteAllText("C:\Path\Output.txt", $content)
    

    (需要路径,因为 .NET 方法不使用 PowerShell 的“当前位置”。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-21
      • 2020-07-08
      • 1970-01-01
      • 2016-10-27
      • 2015-07-16
      • 1970-01-01
      • 2011-04-30
      相关资源
      最近更新 更多