CLI 命令结构拆解器

把命令文本标注为命令、参数和长短选项,帮助阅读结构;不校验参数含义、版本或执行安全性。

点击解释

用途与使用方法

适合初步识别一条命令里的词项与选项外形。当前结果属于结构标注,不能据此判断命令可运行、flag 的实际作用或风险。

  1. 输入一条已脱敏的命令文本;不要放入令牌、密码或真实私有路径。
  2. 点击“解释”,对照 command、argument、long flag、short flag / stdin 等标签阅读。
  3. 查看目标程序当前版本与帮助,核对参数归属、取值、互斥关系和副作用后,再决定是否执行。

默认输入与实际输出

以下为 2026-10-05 使用页面内置合成示例的浏览器核对记录;没有执行生成的命令、配置或技能。

cli-in: codex exec --skip-git-repo-check --color never -
codex  → command
exec  → argument
--skip-git-repo-check  → long flag
--color  → long flag
never  → argument
-  → short flag / stdin

适用边界

  • 默认示例中 exec 和 never 仅被标为 argument,工具没有解释 exec 子命令或 --color 的取值关系。
  • 默认末尾的 - 被标为 short flag / stdin,这不是对所有命令通用的语义判断。
  • 未验证 shell 引号、变量展开、管道、重定向或多条命令的解析;不要把输出当 shell 语法检查器。

常见问题

显示 long flag 就说明参数有效吗?

不说明。它只描述当前词项的外形;有效性要看对应命令与版本的帮助。

点击解释会运行输入的命令吗?

页面提供文本拆解输出;本次核对没有在终端执行示例命令。实际执行请留在你控制的终端并先审阅。

能判断命令是否安全吗?

不能。命令可能写文件、联网或改变账号状态,需要结合目标程序、环境和授权单独判断。

继续阅读

请只使用脱敏示例,不要粘贴密钥或保密资料。站点的数据处理声明见隐私政策;本次核对没有进行独立网络行为审计。

从词项标签到人工解释:把默认命令再读一遍

页面上方的六行是已有浏览器核对得到的词项标签。下面是另加的人工第二层注解,依据 2026-10-13 查阅的 OpenAI 官方 CLI 参考中的 codex exec 说明,不是“解释”按钮的新输出,也没有执行命令。官方在线文档并不等同于你本机安装版本的帮助。

  1. codex → 程序名:先确认实际解析到哪个程序和版本。文本首词相同,不能证明机器上存在正确的可执行文件。
  2. exec → 子命令:此处选择非交互执行模式。工具把它标成 argument,只说明它没有以连字符开头;不能从标签推出“这是普通提示词”。
  3. --skip-git-repo-check → 不带值的选项:官方含义是允许在 Git 仓库外运行。它不等于取消全部安全限制,也没有给本条命令指定工作目录。
  4. --color never → 选项和值是一组:never 属于 --color 的取值,控制输出颜色;页面单独把 never 标成 argument,不代表它是任务提示词。
  5. 末尾 - → 本例的提示词来源:官方对 exec 的 PROMPT 约定允许用 - 从标准输入读取。应继续追问“标准输入来自哪里、具体内容是什么”,不能把它理解成已经提供了一条任务。

人工审阅结论:这条文本选择了非交互模式、放宽 Git 仓库检查并关闭输出颜色,但没有展示标准输入内容。只靠这条文本,无法确定最终任务、访问资料、文件变更或费用。尤其不能由 never 推断“不审批”或“不运行”:它在这里仅是颜色值。

含空格路径:引号影响的是参数边界

以下仅为 Bash 风格 shell 的静态阅读练习;/tmp/cli demo 是虚构工作目录。本页未验证引号解析,下面没有展示或预测本页对此输入的实际输出。

codex exec --cd "/tmp/cli demo" --color never -

在该 shell 语境下,人工预期 --cd 后收到一个完整路径参数 /tmp/cli demo,包围路径的双引号不作为路径字符传入。这里 --cd 用于设置任务工作目录;工具若只给出词项外形标签,仍不足以确认这一归属关系。

人工预期的参数边界(不是本工具输出):
["exec", "--cd", "/tmp/cli demo", "--color", "never", "-"]

对照错误写法:去掉路径两端引号,写成 --cd /tmp/cli demo,会使普通空格分隔后的 /tmp/cli 和 demo 成为两项。不要直接断言后者一定报错:多出的 demo 如何被接收或拒绝,还取决于目标程序参数规则。要核对的是“路径是否作为一个值传递”,而不是标签总数是否看起来合理。

拿到标签后的四项审阅记录

  • 语法归属:记录子命令、每个选项是否取值,以及剩余位置参数分别是什么;本例把 never 配回 --color,把 - 配回 PROMPT。
  • 版本依据:对照本机对应版本的帮助,确认 exec、--cd、--color 和 PROMPT 规则;若与在线文档不同,先保留差异,不套用本例。
  • 上下文缺口:确认实际工作目录、标准输入内容,以及生效的配置与权限;默认命令没有显式提供这些全部信息。
  • 执行决策:在了解任务可能读取、写入或联网的范围后单独决定是否运行。颜色关闭、词法标签齐全、引号成对都不是安全性结论。

如果输入换成 PowerShell、cmd、含变量展开或管道的命令,应重新确认相应 shell 的规则。本练习只补人工阅读方法,不增加解析器能力,也没有进行终端执行、登录或安装测试。

拆解命令结构

粘贴一行命令后点击拆解。工具把第一个片段标记为 command,把双短横线开头的片段标记为 long flag,把短横线开头且长度不超过三字符的片段标记为 short flag / stdin,其他片段标记为 argument。

阅读示例

输入 codex exec --skip-git-repo-check -,输出会依次标记 codex 为命令、exec 为参数、--skip-git-repo-check 为长选项、单个短横线为短选项或标准输入标记。拆分使用空白字符,带引号的复杂 Shell 表达式不会被完整解析。具体参数作用应结合目标程序的帮助信息核对。

离线实测:看见程序真正收到的参数

前面的人工注解能帮助辨认选项归属,但命令文本并不是程序最终收到的参数列表。实际排错时,空值可能消失,变量里的空格可能拆成两项,通配符也可能先被 shell 换成当前目录里的文件名。下面把目标程序换成一个只打印参数的探针,让这些差异可以直接对照。

本实验只运行页内固定的 Bash 命令和 Python 标准库探针。它在自动清理的临时目录里创建 alpha.csv、two words.csv、sentinel.txt 三个无业务内容的文件,不调用 Codex、不联网、不读取真实仓库,也不执行读者粘贴的命令。不要把探针改成真实的上传、删除或部署程序来“试试看”。

先约定意图:--label 的值可以是空字符串;two words 必须作为一个值;*.csv 要原样交给目标程序,而不是让 shell 展开。这里的 --label 只是探针接收的示例文字,不是宣称任何产品存在此选项。若你的真实意图是枚举文件,则展开结果可能恰好正确,应另写自己的预期。

需要保留的参数列表:
["--label", "", "*.csv", "two words"]

下面分别测试空值、空格和通配符,最后合并验证恢复结果。
各场景精确输出见后文,不把不同命令的结果混为一组。

完整脚本中每个场景启动一个新的 Bash;环境只传入所需字段,固定 C locale,关闭启动脚本,显式设定 IFS 和相关 glob 选项。因此结果不会借用当前终端里的 nullglob 或 BASH_ENV 设置。此处是在缩小实验变量,并非通用的恶意 shell 沙箱。

这里没有用 printf "%s\n" "$@" 的空白行数来推断参数数目:它在零参数时也可能打印空行。探针直接将 sys.argv[1:] 序列化为 JSON,所以零参数是 [],一个空参数是 [""]。两者长度不同,后续程序的行为也可能不同。

引用变量保留空值、星号和带空格文本;未引用时空值消失、星号匹配文件、文本拆分。零参数和一个空参数不同。
图:数组中的一项才是一个参数,空白行不是可靠证据。

保存并运行完整参数探针

需要已经安装的 Bash 和 Python 3。本次实测是 Linux、Bash 5.2.37 与 Python 3.12.14;没有测试 zsh、PowerShell、cmd、其他 shell 或 macOS 内置 Bash。保存下面文件为 argv_lab.py,在空目录执行 python argv_lab.py。没有 Bash 时脚本会停止,不自动换成另一种 shell,也不安装软件。

"""Only executes the fixed commands below, inside a disposable fixture directory."""
import json
import os
from pathlib import Path
import shutil
import subprocess
import sys
import tempfile

EXPECTED = {
    'empty_quoted': ['--label', '', 'tail'],
    'empty_unquoted': ['--label', 'tail'],
    'words_quoted': ['two words'],
    'words_unquoted': ['two', 'words'],
    'glob_quoted': ['*.csv'],
    'glob_unquoted': ['alpha.csv', 'two words.csv'],
    'no_match_default': ['*.missing'],
    'no_match_nullglob': [],
    'explicit_empty': [''],
    'recovered': ['--label', '', '*.csv', 'two words'],
    'direct_argv': ['--label', '', '*.csv', 'two words'],
}
COMMANDS = {
    'empty_quoted': 'empty=""; probe --label "$empty" tail',
    'empty_unquoted': 'empty=""; probe --label $empty tail',
    'words_quoted': 'label="two words"; probe "$label"',
    'words_unquoted': 'label="two words"; probe $label',
    'glob_quoted': 'pattern="*.csv"; probe "$pattern"',
    'glob_unquoted': 'pattern="*.csv"; probe $pattern',
    'no_match_default': 'probe *.missing',
    'no_match_nullglob': 'shopt -s nullglob; probe *.missing',
    'explicit_empty': 'probe ""',
    'recovered': 'empty=""; pattern="*.csv"; label="two words"; '
                 'probe --label "$empty" "$pattern" "$label"',
}
PREFIX = '''set +f
shopt -u nullglob failglob dotglob nocaseglob
unset GLOBIGNORE GLOBSORT
IFS=$' \\t\\n'
probe() { "$PYTHON" "$PROBE" "$@"; }
'''

def require(condition, message):
    if not condition:
        raise AssertionError(message)

def main():
    require(sys.argv[1:] in ([], ['--mutate-empty'], ['--mutate-empty-expectation']), 'unsupported arguments')
    bash = shutil.which('bash', path=os.defpath)
    require(bash is not None, 'Bash is required; no alternate shell is used')
    with tempfile.TemporaryDirectory(prefix='argv-lab-') as folder:
        root = Path(folder)
        probe_file = root / 'probe.py'
        probe_file.write_text('import json, sys\nprint(json.dumps(sys.argv[1:]))\n',
                              encoding='utf-8')
        for name in ('alpha.csv', 'two words.csv', 'sentinel.txt'):
            (root / name).write_text('synthetic fixture\n', encoding='utf-8')
        # Whitelist prevents BASH_ENV, imported functions, and shell options leaking in.
        env = {'PATH': os.defpath, 'LC_ALL': 'C', 'PYTHON': sys.executable,
               'PROBE': str(probe_file)}
        def shell(command):
            return subprocess.run([bash, '--noprofile', '--norc', '-c', PREFIX + command],
                                  cwd=root, env=env, capture_output=True, text=True,
                                  timeout=5, check=False)
        actual = {}
        commands = dict(COMMANDS)
        expected = dict(EXPECTED)
        if sys.argv[1:] == ['--mutate-empty-expectation']:
            expected['no_match_nullglob'] = ['']
        if sys.argv[1:] == ['--mutate-empty']:
            commands['empty_quoted'] = COMMANDS['empty_unquoted']
        for name, command in commands.items():
            result = shell(command)
            require(result.returncode == 0 and result.stderr == '',
                    f'{name}: unexpected process failure: {result.stderr}')
            actual[name] = json.loads(result.stdout)
            require(actual[name] == expected[name],
                    f'{name}: expected {expected[name]!r}, got {actual[name]!r}')
        # A process argument list does not ask a shell to expand the literal values.
        direct = subprocess.run([sys.executable, str(probe_file), '--label', '',
                                 '*.csv', 'two words'], cwd=root, env=env,
                                capture_output=True, text=True, timeout=5, check=False)
        require(direct.returncode == 0 and direct.stderr == '', 'direct_argv failed')
        actual['direct_argv'] = json.loads(direct.stdout)
        require(actual == expected, 'whole result differs from fixed oracle')
        fail = shell('shopt -s failglob; probe *.missing')
        require(fail.returncode != 0 and fail.stdout == '' and bool(fail.stderr),
                'failglob must reject before the probe prints its argument array')
        # Negative controls: bad versions must not satisfy the intended contract.
        require(actual['empty_unquoted'] != EXPECTED['empty_quoted'],
                'empty-argument negative control was not detected')
        require(actual['words_unquoted'] != EXPECTED['words_quoted'],
                'word-splitting negative control was not detected')
        require(actual['glob_unquoted'] != EXPECTED['glob_quoted'],
                'wildcard negative control was not detected')
        require(actual['no_match_nullglob'] != actual['explicit_empty'],
                'zero arguments confused with one empty argument')
        require(sorted(p.name for p in root.iterdir()) ==
                ['alpha.csv', 'probe.py', 'sentinel.txt', 'two words.csv'],
                'unexpected files in fixture')
        print(json.dumps(actual, ensure_ascii=False, indent=2))
        print('PASS: 11 fixed argv cases; failglob rejected; 4 negative controls')
        print('Bash:', subprocess.check_output([bash, '--version'], env=env,
                                               text=True).splitlines()[0])
        print('Python:', sys.version.split()[0])

if __name__ == '__main__':
    main()

EXPECTED 是手写的固定参数列表,不从被测输出生成。脚本先要求进程正常结束且 stderr 为空,再逐场景比较 JSON 数组。对于 failglob,单独要求非零退出、空 stdout 和非空诊断;不绑定随 Bash 版本可能变化的英文报错全文。

按固定输出定位,再验证修复

2026-10-14 实际离线运行的输出如下。临时目录名不参与期望值;数组保留空字符串及其位置,避免把“没有参数”和“一个空参数”显示成同一条空行。

{
  "empty_quoted": [
    "--label",
    "",
    "tail"
  ],
  "empty_unquoted": [
    "--label",
    "tail"
  ],
  "words_quoted": [
    "two words"
  ],
  "words_unquoted": [
    "two",
    "words"
  ],
  "glob_quoted": [
    "*.csv"
  ],
  "glob_unquoted": [
    "alpha.csv",
    "two words.csv"
  ],
  "no_match_default": [
    "*.missing"
  ],
  "no_match_nullglob": [],
  "explicit_empty": [
    ""
  ],
  "recovered": [
    "--label",
    "",
    "*.csv",
    "two words"
  ],
  "direct_argv": [
    "--label",
    "",
    "*.csv",
    "two words"
  ]
}
PASS: 11 fixed argv cases; failglob rejected; 4 negative controls
Bash: GNU bash, version 5.2.37(1)-release (x86_64-pc-linux-gnu)
Python: 3.12.14

empty_unquoted 的空值消失后,tail 紧跟 --label;真实程序可能把它当选项值,也可能拒绝,具体取决于该程序。words_unquoted 把一个文本值拆成两项。glob_unquoted 则得到两个 CSV 文件名,其中 two words.csv 仍是一个参数;不能按打印出来的空格再次把它手工拆开。

未匹配的 *.missing 在本例默认选项下保留原样,启用 nullglob 后变成零个参数;显式的双引号空字符串仍是一个参数。启用 failglob 时则在展开阶段拒绝,探针没有输出参数数组。这三个分支说明:只看命令文本,甚至只看目录,都不足以推断实际参数。

恢复场景给每个变量加双引号,重新得到四项固定列表。direct_argv 用 Python 的进程参数列表传入同样四项,不让 shell 解释这些值;它仍不负责判断目标程序是否支持选项或是否应该执行。修复完成的证据是正确数组恢复,不是仅仅退出码为零。

让检查器故意失败一次

python argv_lab.py --mutate-empty

这个内置负控只把 empty_quoted 场景替换为已写在脚本里的无引号版本,不接受任意代码。实测退出码为 1,最后一行如下;这次失败是预期结果。

AssertionError: empty_quoted: expected ['--label', '', 'tail'], got ['--label', 'tail']

再执行不带参数的 python argv_lab.py,应恢复 PASS。正常运行还检查了空值丢失、单词拆分、文件名展开和零参数四组反例;如果删掉关键验证,不能再沿用本文的“检查通过”结论。

再故意写错“零参数”的预期

执行 python argv_lab.py --mutate-empty-expectation,只把 no_match_nullglob 的预期错写为一个空字符串,真实命令仍保持不变。程序应退出 1,最后一行为下面的诊断。这个反向变体证明检查器不会把 [] 和 [""] 混为一谈。随后去掉变体参数重跑,应恢复 PASS。

AssertionError: no_match_nullglob: expected [''], got []

也可使用 python -O argv_lab.py,以及在两个变体命令的 python 后加 -O。检查用显式异常实现,不依赖会被优化模式移除的 assert;正常运行仍退出 0,两个变体仍退出 1。

把参数证据带回命令审阅

现在可以在审阅记录里分开保存三件事:脱敏后的命令文本、明确的 shell 与环境条件、目标程序实际收到的参数数组。预期是一个空值时,应检查数组里的空字符串,而不是数输出行;预期是一个路径时,应检查它是否完整占据一项。遇到差异,先回到引号、变量内容、目录与 glob 选项,再继续检查目标程序的帮助。

本实验没有修改本页拆解按钮或解析器,也没有浏览器复测新输入。既有按钮仍提供词项结构标注;页内实验是独立的终端练习。它没有证明目标命令安全、选项有效、账号可用或模型任务完成,也没有覆盖重定向、管道、命令替换和所有 shell 语法。

上述资料于 2026-10-14 查阅;官方规则与本机实测版本分别记录。所有文件名、选项文字与输入均为合成教学夹具,没有真实模型、产品 CLI 或生产目录的运行记录。

GNU 在线手册目前标示 Bash 5.3;本文运行的可执行文件报告 Bash 5.2.37(1)-release,不能把在线文档版本写成本机版本。Python 引用固定到 3.12 文档。复现包只包含教学正文、原创示意图、完整源码与正常输出;打开 HTML 无需联网,访问参考链接才需要网络。

常见问题

输入的命令会被执行吗?

不会。工具只输出结构标签,不能判断选项是否存在或命令是否能运行。

继续阅读