Node.js之commander.js学习笔记

Posted 二木成林

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Node.js之commander.js学习笔记相关的知识,希望对你有一定的参考价值。

概述

commander.js可以用来写命令行工具。

官网地址:Commander.js

安装与引入

安装

执行如下命令进行安装,但前提是有node环境,即能使用npm命令进行安装:

npm install --save commander

引入

如果是简单使用,Commander提供了一个全局对象:

// 引入commander模块
const  program  = require('commander');
// 设置程序的版本号
program.version('0.0.1');

如果程序比较复杂,那么创建本地的Command对象更好:

// 引入commander模块
const  Command  = require('commander');
// 创建Command对象
const program = new Command();
// 设置程序的版本号
program.version('0.0.1');

选项

概述

用过命令行的知道rm -r中的-r是选项、node --version中的--version也是选项。

Commander使用.option()方法来定义选项,并且可以设置关于选项的简介描述,其语法如下:

/**
 * program.option(flags, description)
 * 参数说明:
 *  - flags:指的是选项,可以定义一个短选项(如-a)和一个长选项(如--list),短选项与长选项之间使用逗号或空格或竖线(|)进行分隔。例如-a, --list
 *  - description:指的是选项的简介描述信息
 */

说明:

  • option()方法就是用来定义命令行选项的。
  • 每个选项都可以定义一个短选项(短选项就是-a这种的情况,即一个短杠-和一个字符)和一个长选项(长选项就是--list这种的情况,即两个短杠--和一个或多个单词组成)。
  • 短选项和长选项之间可以通过逗号(,)、空格()和竖线(|)。例如:-l, --list采用逗号分隔;-v| --version采用竖线分隔;-r --remove采用空格分隔。
  • 对于多个单词的长选项,选项名会转为驼峰命名法(camel-case),例如--template-engine选项可通过program.opts().templateEngine获取。
  • 多个短选项可以合并简写,其中最后一选项可以附加参数。如-a -b -p 80可以合并简写为-ab -p80,甚至简写为-abp80的形式。
  • 短选项和长选项不是同时必须的,可以只有短选项如program.option('-p','显示端口号');,也可以只有长选项如program.option('--port','显示端口号');

例如:

// 使用逗号进行分隔短选项和长选项
program.option('-l, --list', '显示列表信息');
// 使用竖线进行分隔短选项和长选项
program.option('-v| --version', '显示版本信息');
// 使用空格进行分隔短选项和长选项
program.option('-r --remove', '删除');
// 只有短选项
program.option('-p','显示端口号');
// 只有长选项
program.option('--port','显示端口号');
// 多个单词的长选项
program.option('--template-engine','模板引擎');

常用选项类型:boolean型选项和带参数选项

boolean型选项

该种类型的选项无需配置参数,如node --version后面就没有参数。例如:test.js

// 引入commander模块
var program = require('commander');
program.version('0.0.1');

// 设置选项,boolean类型的选项,不携带参数
program.option('-l, --list', '显示列表信息');
program.option('-v| --version', '显示版本信息');

// 处理参数
program.parse(process.argv);

// 获取选项
var options = program.opts();
// 如果是`list`选项,则进行处理
if (options.list) 
    console.log('list选项');

// 如果是`version`选项,则进行处理
if (options.version) 
    console.log('version选项');

如果想要测试这些选项,可以使用node命令调用该js文件进行测试。

说明:

  • node指的是在node环境下,如果要执行js文件就需要使用node命令。
  • test.js指的是当前的js文件,包含了我们刚刚写的代码,也是选项的逻辑处理代码。
  • -l--list--version就是我们在代码种设置的选项,而打印的结果就是代码种根据逻辑判断做出的处理。
  • 处理选项时的if (options.list)中的list就是在option()方法中设定的长选项名list,也可以用短选项名。

带参数选项

选项后面是可以跟着参数的,如rm -rf hello.txthello.txt就是参数,表示待删除的文件。需要注意下声明待参数的选项的语法:option('-l, --list <file>')。即参数是包括在尖括号<>中。例如:test.js

// 引入commander模块
var program = require('commander');
program.version('0.0.1');

// 设置选项,待参数的选项,<directory>就是参数,尖括号是必须的
program.option('-l, --list <directory>', '显示目录中的文件列表信息');
program.option('-r, --remove <file>', '删除指定文件');
program.option('-v| --version', '显示版本信息');

// 处理参数
program.parse(process.argv);

// 获取选项
var options = program.opts();
// 如果是`list`选项,则进行处理
if (options.list) 
    // options.list就是参数值
    console.log('list选项,参数值:' + options.list);

// 如果是`remove`选项,则进行处理
if (options.remove) 
    console.log('remove选项,参数值:', options.remove);

// 如果是`version`选项,则进行处理
if (options.version) 
    console.log('version选项');


说明:

  • options.list既可以判断是否有该选项,又是在有该选项的情况下后面附加的参数值。
  • 如果在option()方法中设置了选项附带参数,则必须输入参数,否则会报错。
  • 如果输入多个参数则只会接受第一个参数,如node test.js --remove /root/hello.txt /root/home

选项的默认值

选项是可以设置一个默认值的,基本语法如下:

/**
 * program.option(flags, description, defaultValue)
 * 参数说明:
 *  - flags:指的是选项,可以定义一个短选项(如-a)和一个长选项(如--list),短选项与长选项之间使用逗号或空格或竖线(|)进行分隔。例如-a, --list
 *  - description:指的是选项的简介描述信息
 *  - defaultValue:指的是设置的该选项的默认值
 */

例如:

// 引入commander模块
var program = require('commander');
program.version('0.0.1');

// 设置选项默认值
program.option('-l, --list <directory>', '显示目录中的文件列表信息', '/home');
program.option('-v| --version', '显示版本信息');

// 处理参数
program.parse();

// 获取选项
var options = program.opts();
// 如果是`list`选项,则进行处理
if (options.list) 
    // options.list就是参数值
    console.log('list选项,参数值:' + options.list);

// 如果是`version`选项,则进行处理
if (options.version) 
    console.log('version选项');


说明:

  • 选项可以设置一个默认值,但跟具体的选项无关。如果在不同的options()方法设置了不同的默认值,也只会使用一个。
  • 调用带有默认值的选项时,不需要输入选项,只需要调用执行命令即可。

其他的选项类型:取反选项和可选参数的选项

取反选项

可选参数选项

所谓的可选参数指的是既可以选择输入参数,又可以选择不输入参数。

选项的参数使用方括号声明表示参数是可选参数(如--optional [value])。该选项在不带参数时可用作 boolean 选项,在带有参数时则从参数中得到值。例如:

// 引入commander模块
var program = require('commander');
program.version('0.0.1');

// 设置选项的可选参数
program.option('-l, --list [directory]', '显示目录中的文件列表信息');

// 处理参数
program.parse(process.argv);

// 获取选项
var options = program.opts();
// 如果是`list`选项,则进行处理
if (options.list === undefined) 
    console.log('没有list选项')
 else if (options.list === true) 
    console.log('有list选项,没有参数')
 else 
    console.log('有list选项,有参数:' + options.list)


说明:

  • 当没有选项的时候,为undefined
  • 当有选项但没有输入参数的时候,得到的是一个布尔值;当有选项但有输入参数的时候,得到的却是参数的值。

必填选项

所谓的必填选项就是输入命令的时候必须携带该选项,否则报错。

通过.requiredOption()方法可以设置选项为必填。其中.requiredOption()方法的语法如下:


/**
 * program.option(flags, description, [defaultValue])
 * 参数说明:
 *  - flags:指的是选项,可以定义一个短选项(如-a)和一个长选项(如--list),短选项与长选项之间使用逗号或空格或竖线(|)进行分隔。例如-a, --list
 *  - description:指的是选项的简介描述信息
 *  - defaultValue:指的是选项默认值
 */
program.requiredOption(flags, description);
program.requiredOption(flags, description, defaultValue);

必填选项要么设有默认值,要么必须在命令行中输入,对应的属性字段在解析时必定会有赋值。该方法其余参数与.option()一致。例如:

// 引入commander模块
var program = require('commander');
program.version('0.0.1');

program.option('-l, --list', '显示文件列表信息');
// 设置必填选项
program.requiredOption('-s, --select', '选择文件');


// 处理参数
program.parse(process.argv);

// 获取选项
var options = program.opts();
// 如果是`list`选项,则进行处理
if (options.list) 
    console.log('list选项')

// 如果是`select`选项,则进行处理
if (options.select) 
    console.log('select选项')


说明:

  • 必填选项是执行该命令必须要设置的选项,即使是使用其他非必须选项也必须要设置必填选项。如node test.js没有写必填选项报错了;node test.js --list使用了非必须选项但没有设置必填选项仍然报错了。

变长参数选项

所谓的变长参数,即当你不确定参数的数量,可能是一个、三个或五个时,就使用变长参数。

定义选项时,可以通过使用...来设置参数为可变长参数。

在命令行中,用户可以输入多个参数,解析后会以数组形式存储在对应属性字段中。在输入下一个选项前(---开头),用户输入的指令均会被视作变长参数。与普通参数一样的是,可以通过--标记当前命令的结束。基本语法如下:

// 普通参数中的变长参数
program.option('-l, --list <direcotry...>', 'description text')
// 可选参数中的变长参数
program.option('-l, --list [directory...]', 'description text')

例如:

// 引入commander模块
var program = require('commander');
program.version('0.0.1');

program.option('-l, --list <directory...>', '显示指定目录下文件列表信息');
program.option('-r, --remove [file...]', '删除指定文件');

// 处理参数
program.parse();

// 获取选项
console.log(program.opts());
// 获取选项后面的参数
console.log(program.args)

版本选项

版本选项就是设置版本号,是通过.version()方法来进行设置,其默认选项为-V--version。设置了版本后,命令行会输出当前的版本号。语法如下:

/**
 * program.version(str[,flags,description])
 *  参数:
 *   - str:版本号字符串
 *   - flags:选项名称,默认是-V和--version
 *   -description:该选项的描述性信息
 */
// 只指定版本号,是一个字符串
program.version(str);
// 还支持自定义选项名称,选项的描述信息
program.version(str, flags, description);

例如:

// 引入commander模块
var program = require('commander');
program.version('0.0.1', '-v, --ver', '版本信息');

// 选项处理
program.parse();

其他选项配置

大多数情况下,选项均可通过.option()方法添加。但对某些不常见的用例,也可以直接构造Option对象,对选项进行更详尽的配置。例如:

// 引入commander模块
const Command, Option = require('commander');
const program = new Command();
program.version('0.0.1', '-v, --ver', '版本信息');

program
    // 隐藏帮助信息
    .addOption(new Option('-s, --secret').hideHelp())
    // 通过default()方法设置默认值
    .addOption(new Option('-t, --timeout <delay>', 'timeout in seconds').default(60, 'one minute'))
    // 通过choices()方法设置参数值只能选择设定的值
    .addOption(new Option('-d, --drink <size>', 'drink size').choices(['small', 'medium', 'large']));

program.parse();

// 选项处理
// 忽略...

注意:

  • 如果要使用Option对象,需要引入const Command, Option = require('commander');

自定义选项处理

如面对选项参数复杂的情况,可以通过自定义函数来进行处理。基本语法如下:

/**
 * program.option(flags, description, fn, defaultValue);
 * 参数:
 *  - flags:指的是选项信息
 *  - description:选项的描述信息
 *  - fn:参数的处理函数,该函数接收两个参数:
 *      - value:用户新输入的值
 *      - previous:当前已有的参数值(即上一次调用自定义处理函数后的返回值)
 *  - defaultValue:选项的默认值
 * 返回值:
 *  - 返回新的选项参数值
 */
program.option(flags, description, fn, defaultValue);

自定义函数适用场景包括参数类型转换,参数暂存,或者其他自定义处理的场景。

例如,将输入的绝对路径转换成文件名:

// 引入commander模块
const Command, Option = require('commander');
const program = new Command();
program.version('0.0.1', '-v, --ver', '版本信息');

// 处理list选项参数的函数
var listFn = function (value, previous) 
    // 输入的文件列表是使用逗号进行分隔的字符串,把它切割成数组,获取它们的文件名
    var list = value.split(',');
    list = list.map(item => 
        // 由文件的绝对路径获取文件的文件名
        return item.substring(item.lastIndexOf('/') + 1);
    );
    return list;
;

program.option('-l, --list <file>', '输入文件列表,使用逗号进行分隔', listFn, '/a.txt,/root/b.jpg,/home/hello.log')

program.parse();

// 选项处理
if (program.opts().list) 
    console.log('list选项,参数值:' + program.opts().list);

实战

利用 commander.js 写了一个简单的回收站程序: linux-trash-nodejs

以上是关于Node.js之commander.js学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

node.js学习笔记之简洁聊天室

node.js学习笔记之babel使用

node.js学习笔记之React

node.js学习笔记之写文件

node.js学习笔记之写文件

node.js学习笔记之调用函数