在启动 Angular e2e 测试时,我需要基于 gopass key 创建一个 JSON 文件。不幸的是,我得到的 JSON 编码为带有 BOM 的 UTF-8。
我在由启动配置之一启动的tasks.json中创建了任务,尝试配置它但没有成功。问题是由 PowerShell 引起的,它默认写入带有 BOM 字符的文件。 我试图更改要处理的任务类型(也使用密钥和输出文件作为参数运行),但随后我遇到了未选择正确的 gopass 键或运行命令的问题。 我无法在测试代码中进行微小的更改,因此我需要通过tasks.json/launch.json来设置它。
我当前的任务配置:
{
"type": "shell",
"label": "Get data",
"command": "gopass \"somekey\" > \"myFile.json\""
},
我想获取不带BOM字符的JSON文件
Theo 的回答向您展示了如何在 Windows 上制作 Visual Studio Code 的默认 shell,Windows PowerShell,创建 BOM-less UTF-8 文件,不幸的是,这非常麻烦,因为标准不支持它运算符和 cmdlet。
您的情况最短的表述是替换:
"command": "gopass \"somekey\" > \"myFile.json\""
与:
"command": "[IO.File]::WriteAllLines(\"$pwd\myFile.json\", (gopass \"somekey\"))"
为了保留将
tasks.json
任务定义为可使用 >
的未修改的 PowerShell 命令字符串的便利性,同时还生成无 BOM 的 UTF-8 输出,您可以 使您的任务使用 PowerShell Core 7 作为而是使用 shell,因为它的文件输出 cmdlet 和重定向运算符始终default 为无 BOM UTF8:
先决条件:
确保已安装 PowerShell (Core) 7。
底部显示如何执行自动按需安装。
如果您同意全局用 PowerShell (Core) 7 替换 Windows PowerShell - 那么需要不更改您的任务定义:
注意:这意味着集成终端以及
"shell"
中的所有tasks.json
类型任务将使用PowerShell 7。
打开
setting.json
(从命令面板中选择 > Preferences: Open Settings (JSON)
)并添加以下属性:
"terminal.integrated.defaultProfile.windows": "PowerShell",
注意:如果
pwsh.exe
不在您系统的 PATH
中,请在 "executable"
属性中指定 full路径;您可以通过打开 PowerShell 7 窗口并执行
(Get-Process -Id $PID).Path
. 来获取它
或者,如果您想用 PowerShell (Core) 7 替代 Windows PowerShell 单独任务:
将
"option"
对象添加到任务定义 JSON,以使其使用 PowerShell Core 的 CLI 而不是 Windows PowerShell:
{
"type": "shell",
"label": "Get data",
"command": "gopass \"somekey\" > \"myFile.json\""
"options": {
"shell": {
"executable": "pwsh.exe",
"args": [ "-noprofile", "-command" ]
}
}
}
由于执行 PowerShell 7 的自动化用户级安装很容易,因此您可以完全自动化整个过程,如下所示:
在项目的
tasks.json
文件中,定义一个新的 EnsurePsCoreInstalled
任务,用于检查 PowerShell 7 是否存在并安装它(如果尚不存在)。
它将安装到
$env:LOCALAPPDATA\powershell
。
正如预期的那样,当按需安装发生时(每台机器一次),将会有明显的延迟。
重要:一次性安装后Visual Studio Code 不会立即找到
pwsh.exe
,因此您需要:
code
)。{
"label": "EnsurePsCoreInstalled",
"type": "process",
"command": "powershell.exe",
"args": [
"-noprofile",
"-command",
"if (gcm -ea ignore pwsh) { exit 0 }; Write-Verbose -vb 'Installing PowerShell Core...'; iex \"& { $(irm https://aka.ms/install-powershell.ps1) }\"; $dir = $env:LocalAppData + '\\Microsoft\\PowerShell'; $userPath = [Environment]::GetEnvironmentVariable('Path', 'User') -split ';' -ne ''; if ($dir -notin $userPath) { [Environment]::SetEnvironmentVariable('Path', ($userPath + $dir) -join ';', 'User') }; $env:Path += ';' + $dir; if (gcm -ea ignore pwsh) { Throw 'PowerShell Core was just installed on demand. To make it usable, log off and on again or reboot, or restart Visual Studio Code from a new PowerShell window (run `code`).' } else { Throw 'Installation of PowerShell Core FAILED.' }"
],
"problemMatcher": []
}
要让您的
Get Data
任务首先执行任务 EnsurePsCoreInstalled
,请向其添加以下属性:
"dependsOn": "EnsurePsCoreInstalled"
注意:这样做会减慢您的任务速度,因为任务
EnsurePsCoreInstalled
将首先被调用每次。虽然如果发现 PowerShell Core 已安装,它会快速返回,但运行该任务的 Windows PowerShell 本身具有明显的启动成本。
据我了解,从 PowerShell 版本 6 开始,
Set-Content
和 Out-File
都支持 UTF8NoBOM 编码。
如果您的版本低于6.0,您可以使用下面的任一代码将json字符串保存为不带BOM的UTF8:
$json = @"
{
"type": "shell",
"label": "Get data",
"command": "gopass \"somekey\" > \"myFile.json\""
}
"@
使用 UTF8Encoding 对象,并将
encoderShouldEmitUTF8Identifier
参数设置为 $false
$Utf8NoBom = New-Object System.Text.UTF8Encoding $false
[System.IO.File]::WriteAllText('D:\launch.json', $json, $Utf8NoBom)
或
使用 StreamWriter 对象,默认情况下输出不带 BOM 的 UTF8
$sw = New-Object System.IO.StreamWriter 'D:\launch.json'
$json | Out-String -Stream | ForEach-Object { $sw.Write($_) }
$sw.Dispose()
如果使用set-content,就不会有bom。 PS 5 中的默认值是“ansi”。
或者您可能在谈论 vscode 本身? 默认保存编码是utf8 no bom。