实现简单的命令注册和参数解析
1 )概述
- 这里不会使用任何第三方工具,而是给大家讲解一下参数解析的一个实现原理
- 实现两个目标
- 第一目标是注册一个命令 $
xyzcli init
这个命令就可以完成一个自己的操作 - 第二个是实现参数解析
- 希望能够实现 --version 的一个参数解析
- 以及 init -name 这样的一个参数解析
- 第一目标是注册一个命令 $
2 )实现
-
那么问题来了,如何能识别到这个 init 命令 $
xyzcli init
-
在nodejs中有一个
process
的内置库 -
在 process 中会有一个
argv
参数,这个就会把我们所有的参数给罗列下来- 第1个返回值是:当前node命令的具体路径
- 第2个返回值是:当前脚手架命令,如xyzcli的具体路径
- 第3个返回值是:command, 在这里可以就是 init
#!/usr/bin/env node// 定义执行命令的库 const lib = {init() {console.log('init')} }// 获取并解析 argv const { argv } = require('process'); // console.log(argv) const command = argv[2]; // console.log(command); // init if (command && lib[command]) {lib[command](); // 执行 } else {console.log('请输入命令') }
-
通过以上方法,就可以解析出来 init 命令
-
那如果需要解析出 --name ooo 这种参数呢?
#!/usr/bin/env nodeconst { argv } = require('process');const options = argv.slice(3); // 解析从第3个后面 let [option, param] = options; option = option.replace('--', '');// 测试参数 console.log('option: ', option); // name console.log('param: ', param); // ooo
-
如何应用参数呢?
#!/usr/bin/env node// 定义执行命令的库 const lib = {init({ option, param }) {console.log('执行 init 流程', option, param)} }// 获取并解析 argv const { argv } = require('process'); const command = argv[2]; let option, param; const options = argv.slice(3); if (options) {[option, param] = options;option = option.replace('--', ''); } if (command && lib[command]) {lib[command]({ option, param }); // 执行 } else {console.log('请输入命令') }
-
注意,实际参数解析往往比较复杂,比如:
- $
xyzcli init --name -p 22 --test 33
- 这种往往参数比较复杂,而且对应的值非常不确定,这个时候,参数处理就会变得非常困难
- 如果自己开发和兼容此类问题,将会占用非常大的工作
- 通常我们用一些库进行处理, 这里只做原理解析
- $
-
对全局命令的处理 $
xyzcli --version
- 注意,这里 --version 属于 command, 也就是出现在了 argv 的第三位
- 这种,就是顶级的或全局的 option
#!/usr/bin/env node// 定义执行命令的库 const lib = {init({ option, param }) {console.log('init');console.log('执行 init 流程', option, param);},version: '1.0.0' } // 获取并解析 argv const { argv } = require('process'); const command = argv[2]; let option, param; const options = argv.slice(3); if (options.length) {[option, param] = options;option = option.replace('--', ''); }// 执行命令 if (command && lib[command]) {lib[command]({ option, param }); // 执行 } else if(command.startsWith('--') || command.startsWith('-')) {// 这里是全局 optionsconst globalOption = command.replace(/--|-/g, '');if (globalOption === 'version' || globalOption === 'V') {console.log(lib['version']);} } else {console.log('请输入命令') }
-
以上演示,完成整个脚手架的一个初步版本开发
-
注意这里不是成熟的案例,只是阐述如何做的原理