{1..3}a 如何变成 1a 2a 3a?BashSupport 花括号展开引擎源码级解读

📅 2026/8/22 14:52:34
{1..3}a 如何变成 1a 2a 3a?BashSupport 花括号展开引擎源码级解读
{1..3}a 如何变成 1a 2a 3aBashSupport 花括号展开引擎源码级解读【免费下载链接】BashSupportBash and shell script language support for JetBrains IDEs. Please refer to www.bashsupport.com/news/bashsupport-pro-1.3/ for the reasons.项目地址: https://gitcode.com/gh_mirrors/ba/BashSupportBashSupport 是一款为 JetBrains IDE 提供 Bash 与 Shell 脚本语言支持的插件它的花括号展开引擎brace expansion engine可以在不执行 Shell 的情况下把{1..3}a这类写法静态计算出1a 2a 3a。 本文将从新手视角沿着源码带你走完整条计算链路从解析器识别、模式拆分到范围求值与最终拼装。先搞懂什么是花括号展开为什么需要静态计算在终端里输入echo {1..3}a # 输出1a 2a 3aBash 会在执行前把{1..3}a展开成三个词。但 IDE 的编辑器不能真正执行你的脚本——它只能在后台算出来用于检查高亮、代码修复建议等场景。这就是静态计算不运行 Shell仅靠文本分析模拟展开结果。第一阶段解析器识别出这是一个花括号展开入口在解析函数 src/com/ansorgit/plugins/bash/lang/parser/misc/BraceExpansionParsing.javaisValid()方法会向前窥探 10 个 token确认词内部是否存在左花括号{避免把普通变量${x}误判doParse()按前缀 →{→ 值与逗号 →}→ 后缀的顺序逐个消费 token解析成功后用marker.done(EXPANSION_ELEMENT)把整段标记为一个展开元素该类型定义在 src/com/ansorgit/plugins/bash/lang/parser/BashElementTypes.java 中EXPANSION_ELEMENT new BashElementType(single bash expansion)。随后 src/com/ansorgit/plugins/bash/lang/psi/BashPsiCreator.java 将这个节点包装成 PSI 对象BashExpansionImpl它是编辑器检查功能的抓手// BashExpansionImpl.java 核心方法 public boolean isValidExpansion() { return ValueExpansionUtil.isValid(getText(), BashProjectSettings.storedSettings(getProject()).isSupportBash4()); }注意最后这个参数是否启用 Bash 4 增强语法是项目级设置直接决定后面能否支持步长与零填充。第二阶段把{1..3}a拆成迭代块 静态块核心计算工具是 src/com/ansorgit/plugins/bash/lang/valueExpansion/ValueExpansionUtil.java。split()方法以{为分隔符切割原文把每个片段归类为两种单元片段生成对象职责{1..3}IteratingExpansion迭代展开多值逐个产出1 → 2 → 3aStaticExpansion静态展开单值始终产出a对应实现分别位于src/com/ansorgit/plugins/bash/lang/valueExpansion/IteratingExpansion.javasrc/com/ansorgit/plugins/bash/lang/valueExpansion/StaticExpansion.java两者统一实现接口 src/com/ansorgit/plugins/bash/lang/valueExpansion/Expansion.java只有三个方法findNext()取下一个值、isFlipped()是否已翻回首位、hasNext()是否还有值——像一组只读指针非常简洁。第三阶段范围表达式{1..3}的静态求值evaluateExpansionPattern()负责把花括号内部的文本求值成字符串列表规则与真实 Bash 对齐范围必须独占整个展开块若花括号内既有逗号又有..整体按普通字符串处理数字范围1..3→1, 2, 3起点大于终点时自动取负步长5..1→5 4 3 2 1单字符范围a..z按 ASCII 递增展开Bash 4 增强语法由enhancedSyntax开关控制步长1..10..2→1 3 5 7 9零填充001..005→001 002 003 004 005按起点/终点最长宽度左补零。这个增强支持也记录在 Changelog.md 中Bash v4 support: Support the enhanced syntax of brace expansions, e.g. (001..010..3)。求值失败时如1..a方法返回空列表split()抛出IllegalArgumentException最终isValid()判定为非法展开——与 Bash 对非法模式原样保留的行为一致。第四阶段迭代拼装——翻牌器式的最终输出expand()是最妙的一步。它把展开单元列表反转后反复执行makeLine()每轮从最外层单元开始调用findNext(lastFlipped)并把结果插到行首配合反转列表恰好还原原始顺序只有当前一个单元翻转翻回首位时外层单元才前进一格——这正是里程表/嵌套 for 循环的语义。因此{1,2}x{3,4}的展开轨迹为轮次内层{3,4}外层{1,2}静态x输出行131x1x3241x1x43翻回 31→2x2x3442x2x4最终拼出1x3 1x4 2x3 2x4与 Bash 实际输出完全一致。✅IDE 中的落地检查与一键替换静态计算的结果并不只用于内部验证。src/com/ansorgit/plugins/bash/editor/inspections/inspections/EvaluateExpansionInspection.java 会对合法的花括号展开提供检查提示配套的 src/com/ansorgit/plugins/bash/editor/inspections/quickfix/EvaluateExpansionQuickfix.java 则调用ValueExpansionUtil.expand()把{1..3}a直接替换成计算后的1a 2a 3a——你在编辑器里看到的评估展开快速修复底层就是这套引擎。获取源码与验证方式想亲手跑一遍这套引擎可克隆仓库并运行相关测试git clone https://gitcode.com/gh_mirrors/ba/BashSupport重点测试与资料解析层测试test/com/ansorgit/plugins/bash/lang/parser/misc/BraceExpansionParsingTest.java展开快速修复测试数据testData/psi/inspection/evaluateExpansionInspection/项目已知问题清单KNOWN_ISSUES.md总结一张表看懂整条链路阶段关键文件做什么识别src/com/ansorgit/plugins/bash/lang/parser/misc/BraceExpansionParsing.java从词 token 中认出前缀{值}后缀结构建模src/com/ansorgit/plugins/bash/lang/psi/BashPsiCreator.java生成BashExpansionImplPSI 节点拆分src/com/ansorgit/plugins/bash/lang/valueExpansion/ValueExpansionUtil.java切分为迭代块与静态块求值同上evaluateRangeExpression数字/字符范围、步长、零填充拼装同上expand IteratingExpansion.java翻牌器式迭代生成最终结果应用EvaluateExpansionQuickfix.java检查提示与一键替换BashSupport 用不到两百行核心代码就静态复现了 Bash 花括号展开的完整语义——理解了Expansion接口的三个方法与翻转机制你也就掌握了这类文本静态求值引擎的通用设计思路。【免费下载链接】BashSupportBash and shell script language support for JetBrains IDEs. Please refer to www.bashsupport.com/news/bashsupport-pro-1.3/ for the reasons.项目地址: https://gitcode.com/gh_mirrors/ba/BashSupport创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考