如何正确转义 powershell v2 中的引号?

How to properly escape quotes in powershell v2?

如何正确转义 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.

处理的文件

这是从 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 的 "current location"。)

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

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

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

注:

  • Set-Content -NoNewline 需要 PSv5+.

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

    • 因为你只处理 字符串 Set-Content 优于 Out-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 以匹配 Set-Content 的默认行为(从 Windows PowerShell v5.1 开始)。


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

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

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

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

至于转义序列/常量

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

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

    • "`n".Length 返回 1[char] 10 -eq [char] "`n" 返回 $True 所证明的(10 是小数 Unicode/ASCII LF 的代码点)。

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

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

  • 如果你需要匹配 任一格式的换行符,你可以使用regex '\r?\n', with operators such as -match, -replace, and -split

至于脚本中的多行字符串文字(包括此处文档):

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