ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

PowerShell 5.1 中文环境 8 条铁律

PowerShell 5.1 中文环境 8 条铁律 # PowerShell 5.1 中文环境 8 条铁律 一份从 1670 次实战失败中蒸馏的 PS5.1 中文避坑手册。 联合产出Minimax CodeMiniMax Code, MiniMax 出品 幽大人。所有断言附失败化石来源。TL;DR 速览PS5.1 中文脚本必须 UTF-8 BOM。bash 调用 PowerShell 用单引号。Out-File 显式指定 UTF8 编码。空参数用引号包裹或跳过。避免 ----- 装饰用变量间接。详细内容见下文各铁律。## 为什么写这篇Windows 10 默认 PowerShell 是 5.1。中文 Windows 上 PS5.1 默认按 cp936 解析所有未指定编码的文本文件。这两个事实叠在一起在 AI 协作流水线、批量脚本、本地化部署、CI/CD 各类场景里制造了大量灵异失败同样的脚本在英文 Windows 上跑通中文 Windows 上跑出乱码 / 参数丢失 / 中文路径错误。本文不讨论 PowerShell 7 (pwsh)因为 7 已默认 UTF-8 解决大部分痛点。本文专注 PS5.1。8 条铁律每条都附症状、根因、修复、失败化石。---## 铁律 1.ps1 含中文 → 必须 UTF-8 BOM**症状**Write-Host 10_主题区 # 实际输出10_涓婚**根因**PS5.1 默认按系统代码页cp936 on CN Windows解析 .ps1 文件。UTF-8 编码的中文 3 字节序列被读作 cp936 → mojibake → 后续解析器看到的是乱码字符串。**修复**powershell# 方法 A加 UTF-8 BOM [System.IO.File]::WriteAllText($p, $content, (New-Object System.Text.UTF8Encoding $true)) # 方法 B编辑器另存为 UTF-8 with BOM # 方法 C把中文外置到 JSONUTF-8 BOM脚本只读 JSON**失败化石**月批编排器 _stage2_batch_runner.ps1无 BOM解析失败导致后续所有 LLM 路由 ABORT。---## 铁律 2bash -Command $VAR 会吃掉 $**症状**powershell -Command Write-Host $foo# PowerShell 实际看到Write-Host foo → $foo 是空**根因**bash 在 -Command ... 双引号字符串里会先做变量展开。如果 $foo 没转义成 \$foobash 会先吃 $再把空值传给 PowerShell。**修复**bash# 方法 A单引号不展开 powershell -Command Write-Host $foo # 方法 B写到 .ps1 文件值通过 -File script.ps1 -Param $foo 传 # 不要在 bash inline 里 -Command 双引号**失败化石**多次 _probe_remaining.ps1 调用失败所有 $VAR 被吃成字面量 VAR。---## 铁律 3PS5.1 -- token 解析陷阱**症状**powershellWrite-Host ----- 开始# ParseError: Missing expression after unary operator --.**根因**PS5.1 token 解析器在某些上下文里会把字符串 ----- 错误识别为 -- -减减操作符 负号触发 parse error。**修复**powershell# 方法 A变量间接 $msg ----- 开始 ----- Write-Host $msg # 方法 B避免 ----- 装饰改用 或 **** # 方法 C单引号前加空格 Write-Host ----- 开始**失败化石**多个脚本首次运行即报 ParseError反复排查才能定位到 -- token。---## 铁律 4-Param $emptyVar 会吞掉空参数**症状**powershell$emptyList powershell -File child.ps1 -Candidates $emptyList# child.ps1 内param([string]$Candidates )# 报错Missing an argument for parameter Candidates.**根因**当 $emptyVar PS5.1 把 -Candidates 当作有名字但无值的参数-Candidates 后空。子脚本 param([string]$Candidates ) 的默认值不生效因为参数名已存在但值为空。**修复**powershell# 方法 A显式空字符串 powershell -File child.ps1 -Candidates $emptyList # 方法 B子脚本先判断 if ($PSBoundParameters.ContainsKey(Candidates)) { ... } # 方法 C不要传空压根跳过 child**失败化石**S2c LLM 路由子进程因 -Candidates 空参数失败所有 S2c 调用 ABORT。---## 铁律 5Out-File 默认 UTF-16 LE不是 UTF-8**症状**powershell中文 | Out-File log.txt# log.txt 里\u0000\xE4\x00\xB8\xAD\x00UTF-16 LE 交错**根因**PS5.1 默认 Out-File 用 UTF-16 LEUnicode编码不是 UTF-8。**修复**powershell中文 | Out-File -Encoding UTF8 log.txt # 写 JSONL 时更稳 [System.IO.File]::WriteAllLines($p, $lines, [System.Text.Encoding]::UTF8)**失败化石**多份 .log 文件因 UTF-16 LE 编码被识别失败后续日志分析失败。---## 铁律 6Write-Host (字面量 $var) 闭包参数绑定陷阱假设级**症状**间歇性powershellWrite-Host (foo $a)Write-Host (bar $b)# 第二个 Write-Host 可能报错A positional parameter cannot be found that accepts argument bar.**根因**未完全证实PS5.1 在某些情况下对闭包式 Write-Host 调用的参数绑定顺序判断错误。**修复**powershell$msg1 foo$a $msg2 bar$b Write-Host $msg1 Write-Host $msg2**失败化石**多次观察到间歇性 PositionalParameterNotFound但未完全隔离根因标 C6 假设级。---## 铁律 7生产脚本 BOM 缺失 → 子调用级联失败**症状**所有 run_s2_*.ps1 跑通但 child process 拿到的中文路径全 mojibake后续 scan_s1.jsonl 查找失败 → ABORT: path ... not found。**根因**父脚本读 scan_s1.jsonl 用显式 UTF-8但父脚本**自身的字面量**解析仍走 cp936。当父脚本传中文路径给 childchild 又用自己的 cp936 解析 → 双层 mojibake。**修复**powershell# 一次性给所有 .ps1 加 UTF-8 BOM# 用 _add_bom_all.ps1遍历 _system/scripts/有非 ASCII 字节就加 BOM**失败化石**月批因此中断所有 S2c 阶段级联 ABORT。修复后加 BOM 13 个脚本批次继续。---## 铁律 8嵌套 PowerShell 的 -Param $empty 参数剥离这是铁律 4 的子集但因为出现在 orchestrator → child 链路且伴随 scan_s1.jsonl 缺失条目触发条件不同需单独成律。**修复**铁律 4 的方法全适用。生产脚本最佳实践**在调用 child 前先 Test-Path 验证路径存在**避免空参数链入子进程。---## 8 条速查表速查表\现象修复1中文 .ps1 解析乱码加 UTF-8 BOM2bash -Command $VAR 吃 $单引号或写 .ps1 -Param3----- 触发 ParseError变量间接避免 -----4-Param $empty 吞参数$emptyList或子端默认值5Out-File 默认 UTF-16显式 -Encoding UTF86Write-Host (字var) 间歇错变量间接假设级7生产脚本 BOM 缺失级联一次性加 BOM8嵌套 PowerShell 空参数剥离见铁律 4## 衍生建议如果你正在写 PS5.1 中文 长跑的批处理系统,可以参考。如果你已经在 PowerShell 7 (pwsh) 环境**本文 80% 的陷阱不再存在**但铁律 2bash -Command 吃 $仍适用因为那是 bash 行为不是 PS 行为。## 配套资产- 8 条铁律来源_system/habits_and_mistakes.md 第 §C 节- 失败化石全文_system/fossil.jsonl1670 行公开审计- BOM 预检脚本_system/scripts/_add_bom_all.ps1- 编码诊断脚本_system/scripts/_scan_bom.ps1、_nonascii_scan.ps1## 作者- **Minimax Code**MiniMax Code, MiniMax 出品—— 协作产出的 AI 侧- **幽大人** —— 协作产出的人类侧本文与任何具体项目方法论解耦纯 PS5.1 中文环境工程实录。
返回列表