愿你坚持不懈,努力进步,进阶成自己理想的人

—— 2017.09, 写给3年后的自己

Node命令行程序开发总结

Node可以很方便地进行命令行程序的开发,我们所接触到的sass、less、npm等程序,都是命令行程序。

一、可执行脚本

自从有了Node后,我们就可以使用JavaScript来编写可执行脚本了。最简单的可执行脚本hello如下:

#!/usr/bin/env node
console.log('Hello world!')

修改脚本权限

$ chmod 0755 path/to/hello

执行脚本:

$ ./hello
# 输出 'Hello world!'

我们发现,这里是直接使用./hello的方式执行脚本,而不是node hello.js的方式,这是因为我们使用了#!/usr/bin/env node的缘故。据说程序员都是偷懒的,那么我们觉得./hello也太繁琐了,有没有更简单点的方式呢?
我们可以:
1)将hello的路径加入环境变量PATH
2)使用npm link命令
再执行

$ hello

即可


二、命令行参数的原始写法

命令行参数可以用process.argv获取,如:

#!/usr/bin/env node
console.log('Hello', process.argv[2]);

执行:

$ ./hello RuphiLau
# 输出:Hello RuphiLau

上述例子执行的实际上是:

node hello.js RuphiLau

process.argv将被填充如:

[
    '/usr/local/Cellar/node/7.7.2/bin/node',
    '/Users/Ame/Desktop/Node/hello',
    'RuphiLau'
]


三、新建进程

脚本可以使用child_process模块来新建子进程从而执行Unix系统命令,如:

let name = process.argv[2];
const exec = require('child_process').exec;

let child = exec('echo hello ' + name, (err, stdout, stderr) => {
    if (err) throw err;
    console.log(stdout);
});

执行:

$ ./hello RuphiLau
# 输出:Hello RuphiLau


四、yargs模块

yargs模块可以被方便地用来处理命令行参数,安装方法如:

npm install --save yargs

1、读取参数

对于下列形式的命令行:

$ ./hello --name=RuphiLau
$ ./hello --name RuphiLau

可以方便地进行读取,其方式为:
1)载入yargs模块中的argvconst argv = require('yargs').argv
2)使用argv.name读取

2、一个字母的短参

对于一个字母的短参数,如:

$ ./hello -n RuphiLau

可以用一个字母作为argv对象的键名来指定,如:argv.n

3、长短参结合

如果既希望可以用短参数,又可以用长参数,如:

$ ./hello --name RuphiLau
$ ./hello --name=RuphiLau
$ ./hello -n RuphiLau

那么可以使用alias方法,如:

#!/usr/bin/env node
const argv = require('yargs')
    .alias('n', 'name')
    .argv;

获取的时候则统一使用argv.n获取就可以了

4、非-开头的参数

可以使用argv._获取非-开头的属性,如:

$ ./hello A -n tom B C

argv._的值为:

['A', 'B', 'C']


五、命令行参数的配置

yargs可以使用3个方法来配置命令行参数,如:

  • demand 参数是否必选
  • default 指定默认值
  • describe 指定提示

例子如:

#!/usr/bin/env node
let argv = require('yargs')
    .demand(['n'])
    .default({
        n: 'RuphiLau'
    })
    .describe({
        n: 'Your name'
    })
    .argv;

代码指定参数n不可忽略,并且默认值为RuphiLau
除了这种方式外,我们可以使用option()方法来将所有的这些配置写进一个对象里,如:

#!/usr/bin/env node
let argv = require('yargs')
    .option('n', {
        alias: 'name',
        demand: true,
        default: 'RuphiLau',
        describe: 'Your name',
        type: 'string'
    })
    .argv;

有些情况下,有些参数不需要值,它们起的只是一个开关的作用,这种情况下,可以使用boolean()方法指定参数返回布尔值,比如许多工具里可以用-w选项来配置是否观测文件,那么就可以如下这么使用:

let argv = require('yargs')
    .boolean(['n'])
    .argv;

这种情况下,只要有传开关参数,无论什么情况下都会返回true,只有不传的情况下才会返回false,而这个属性,也可以传入option()方法里(如option({ boolean: true })


六、帮助信息

yargs模块提供了一些有用的方法,来帮助我们生成帮助信息,如:

  • usage 用法格式
  • example 提供例子
  • help 显示帮助信息
  • epilog 出现在帮助信息的结尾

例子如下:

#!/usr/bin/env node
let argv = require('yargs')
    .option('f', {
        alias: 'name',
        demand: true,
        default: 'RuphiLau',
        describe: 'Your name',
        type: 'string'
    })
    .usage('Usage: hello [options]')
    .example('hello -n RuphiLau', 'say hello to RuphiLau')
    .help('h')
    .alias('h', 'help')
    .epilog('Copyright 2015')
    .argv;

执行$ ./node -h得到:

选项:
  -f, --name  Your name                     [字符串] [必需] [默认值: "RuphiLau"]
  -h, --help  显示帮助信息                                                [布尔]

示例:
  hello -n RuphiLau  say hello to RuphiLau

Copyright 2015


七、子命令

对于形如git commit -m风格的命令,yargs也是提供了支持的,主要是通过command()方法,如下:

let argv = require('yargs')
    .command('commit', 'commit your code', function(yargs) {
        let argv = yargs.reset()
            .option('m', {
                alias: 'message',
                description: 'provide any sentence'
            })
            .help('h')
            .argv;

        console.log(argv.m);
    })
    .argv;