如何正确使用 yargs 定义和触发命令行子命令

如何正确使用 yargs 定义和触发命令行子命令

如何正确使用 yargs 定义和触发命令行子命令 — yargs 不触发命令通常是因为命令定义与调用方式不匹配:`command(‘name ‘)` 表示位置参数(非 flag),而 `–flag` 形式需在 builder 函数中显式声明选项;混淆二者会导致解析失败并默认显示帮助页。

在使用 yargs 构建 CLI 工具时,一个常见误区是将命令参数误写为 –add-item 或直接混用短横线命令名与 flag 风格调用(如 node script.js –add-item 1 2)。yargs 的 .command() 方法不支持以 –xxx 开头的命令名,且其语法结构严格区分「命令名」「位置参数」和「选项(flags)」三类元素。

✅ 正确用法:命令 + 选项(推荐用于可读性与健壮性)

若希望支持类似 node my_script.js add-item –val1=3 –val2=55 的调用方式,应将参数定义在 builder 对象中(即第二个参数),而非嵌入命令字符串:

import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';

void yargs(hideBin(process.argv))
  .command(
    'add-item', // ← 命令名(无短横线)
    'Add a new item with two values',
    (yargs) => yargs
      .option('val1', {
        type: 'string',
        demand: true,
        describe: 'The first value (required)',
      })
      .option('val2', {
        type: 'number',
        demand: true,
        describe: 'The second value (required, numeric)',
      }),
    async (argv) => {
      console.log('✅ add-item executed:', { val1: argv.val1, val2: argv.val2 });
      // 实际业务逻辑...
    }
  )
  .command(
    'print',
    'Print a value',
    (yargs) => yargs
      .option('val1', {
        type: 'string',
        demand: true,
        describe: 'Value to print',
      }),
    async (argv) => {
      console.log('?️  print executed:', argv.val1);
    }
  )
  .demandCommand(1, '⚠️  Please specify a command: add-item or print')
  .help()
  .alias('help', 'h')
  .parse();

✅ 调用示例:

node my_script.js add-item --val1="hello" --val2=42
node my_script.js print --val1="world"

? 提示:.option() 自动支持缩写(如 .alias(‘v’, ‘val1’))、类型校验、必填约束(demand: true)及自动帮助文案生成。

⚠️ 错误模式解析

  • ❌ command(‘–add-item ‘):yargs 将 –add-item 视为非法命令名(含 -),直接忽略该命令注册;
  • ❌ command(‘add-item ‘) + node script.js add-item 1 2:此时 v1 和 v2 是位置参数,必须紧随命令名之后、无 — 前缀;但若同时传入其他 flag(如 –debug),它们不会被自动挂载到 argv 中,除非额外调用 .options();
  • ❌ node script.js –add-item 1 2:–add-item 被解析为全局 flag(未定义),yargs 找不到匹配命令,回退至 .help()。

? 补充:纯位置参数模式(仅限简单场景)

若坚持使用位置参数(如 node script.js add-item apple 123),需确保命令定义与调用完全对齐:

OmniAudio

OmniAudio

OmniAudio 是一款通过 AI 支持将网页、Word 文档、Gmail 内容、文本片段、视频音频文件都转换为音频播客,并生成可在常见 Podcast ap

下载

.command(
  'add-item  ',
  'Add item by name and ID',
  {}, // builder 留空或仅配置全局选项
  async (argv) => {
    console.log('?', argv.item, 'ID:', argv.id);
  }
)

调用:

node my_script.js add-item "My Item" 999

⚠️ 注意:此时 argv.item 和 argv.id 类型默认为 string,需手动转换;且无法混合使用 –xxx 标志(除非在全局层定义)。

✅ 最佳实践总结

项目 推荐做法
命令命名 使用 kebab-case(如 add-item),禁用 — 前缀
参数类型 优先用 .option() 显式声明 flag 参数,语义清晰、校验完备、兼容 help
必填控制 使用 demand: true 或 demandOption([‘val1’, ‘val2’])
错误提示 .demandCommand(1, ‘…’) + 自定义 message,提升用户体验
调试技巧 在 handler 中 console.dir(argv, { depth: null }) 查看实际解析结果

遵循以上规范,即可彻底解决 yargs “命令不触发、只显示 help” 的问题,构建出专业、可靠、易维护的 Node.js CLI 工具。

https://www.php.cn/faq/1968205.html

发表回复

Your email address will not be published. Required fields are marked *