从零开始打造个人专属命令行工具集——yargs完全指南

时间:2022-12-18 22:45:12

前言

使用命令行程序对程序员来说很常见,就算是前端工程师或者开发gui的,也需要使用命令行来编译程序或者打包程序

熟练使用命令行工具能极大的提高开发效率,linux自带的命令行工具都非常的有用,但是这些工具都是按照通用需求开发出来的

,如果有一些特别的需求,还是需要自己写脚本来完成一些比如文件批量重命名,文件内容批量替换等任务来提供工作效率。

在node.js出来之前,python经常被用来开发一些脚本完成特殊的任务,比如python爬虫,python相关的教程有很多,有兴趣的自己google。

得益于node.js的异步io特性,使用node开发io密集类任务变得非常简单,这篇文章就为大家讲讲怎么使用node.js的yargs模块来开发自己的命令行工具集合。

命令行参数解析

yargs是一个npm模块用来完成命令行参数解析的,回到使用shell开发命令行的时代,getopts是第一代命令行参数解析工具,经过shell => python => node.js

的迭代,命令行参数解析程序其实没有多大的进化,它们的目的始终是把用户从命令行传入的参数解析成指定的格式,供程序使用

虽然没有多大变化,但是由于开发一个命令行参数解析模块比较简单,所以目前node社区存在很多类似yargs的开源项目,这里简单列举一下,有兴趣的可以自己去了解一下,

然后选择自己喜欢的项目来使用。

yargs

读过阮一峰的Node.js 命令行程序开发教程之后开始使用yargs开发自己命令行工具,

用过一段时间发现非常的好用。

自阮大神的文章发布以来,yargs有了一些改动,添加有很多有用的功能,特别是.commandDir(directory, [opts])这个功能,对打造命令行工具集合非常有用,所以写一个新版本的yargs教程还是有必要的。

yargs的用法还算比较简单,对英文有自信的可以去首页阅读原版:yargs

简单模式

yargs默认使用两个--作为参数的前缀,中间使用空格或者=都可以

下面的代码展示了yargs最简单的用法,你只需要引入yargs,就能读取命令行参数,不需要写任何的配置,非常的简单

#!/usr/bin/env node
var argv = require('yargs').argv; if (argv.ships > 3 && argv.distance < 53.5) {
console.log('Plunder more riffiwobbles!');
} else {
console.log('Retreat from the xupptumblers!');
}
$ ./plunder.js --ships=4 --distance=22
Plunder more riffiwobbles! $ ./plunder.js --ships 12 --distance 98.7
Retreat from the xupptumblers!

示例代码都来自官网:yargs

简单模式还能读取短变量如-x 4相当于argv.x = 4

简单模式还能读取布尔类型-s相当于argv.s = true

简单模式还能读取非-开始的变量,这种类型的变量保存在argv._数组里面

参数配置

简单模式的功能都只用一行代码就能实现

var argv = require('yargs').argv;

但是如果你想统计变量出现的次数怎么办? 答案就是添加参数配置选项。

#!/usr/bin/env node
var argv = require('yargs')
.count('verbose')
.alias('v', 'verbose')
.argv; VERBOSE_LEVEL = argv.verbose; function WARN() { VERBOSE_LEVEL >= 0 && console.log.apply(console, arguments); }
function INFO() { VERBOSE_LEVEL >= 1 && console.log.apply(console, arguments); }
function DEBUG() { VERBOSE_LEVEL >= 2 && console.log.apply(console, arguments); } WARN("Showing only important stuff");
INFO("Showing semi-important stuff too");
DEBUG("Extra chatty mode");

上面的程序能统计verbose参数出现的次数,缩写-v也会统计进去,具体调用例子参考下面的代码

$ node count.js
Showing only important stuff $ node count.js -v
Showing only important stuff
Showing semi-important stuff too $ node count.js -vv
Showing only important stuff
Showing semi-important stuff too
Extra chatty mode $ node count.js -v --verbose
Showing only important stuff
Showing semi-important stuff too
Extra chatty mode

yargs提供很多接口用来帮助完善命令行程序,

提示用法

var argv = require('yargs')
.usage('Usage: $0 -w [num] -h [num]')
.argv;

必选参数

#!/usr/bin/env node
var argv = require('yargs')
.usage('Usage: $0 -w [num] -h [num]')
.demand(['w','h'])
.argv;

提供参数默认值

#!/usr/bin/env node
var argv = require('yargs')
.default('x', 10)
.default('y', 10)
.argv
;
console.log(argv.x + argv.y);

打印帮助信息

#!/usr/bin/env node
var argv = require('yargs')
.usage('Usage: $0 <command> [options]')
.help('h')
.alias('h', 'help')
.epilog('copyright 2015')
.argv;

使用别名

var argv = require('yargs')
.usage('Usage: $0 <command> [options]')
.alias('h', 'help')
.argv;

访问argv.h相当于访问argv.help

参数数组

var argv = require('yargs')
.usage('Usage: $0 <command> [options]')
.alias('n', 'name')
.array('n')
.argv; console.log(argv.n);

调用

node array_test.js -n abc test

设置参数范围

var argv = require('yargs')
.alias('i', 'ingredient')
.describe('i', 'choose your sandwich ingredients')
.choices('i', ['peanut-butter', 'jelly', 'banana', 'pickles'])
.help('help')
.argv

上述代码设定argv.i的值只能是['peanut-butter', 'jelly', 'banana', 'pickles']数组中的一个

上面是yargs比较简单的用法,如果想阅读完整版,建议去github上阅读

子命令

yargs适合开发复杂的命令行程序的另一个原因是它支持子命令,而且子命令可以嵌套,这意味着你也可以开发出类似git这样拥有上百个命令的程序

yargs的子命令有两种模式:.command(*).commandDir(directory, [opts])

.command

.command方法有三个接口

.command(cmd, desc, [builder], [handler])

.command(cmd, desc, [module])

.command(module)

其实它们的用法都差不多,可以把它们都看作传递一个module给yargs,这个module必须导出四个变量

cmd, desc [builder], [handler],其中builder和handler是方法,另外两个是字符串

使用第一个接口的示例

yargs
.command(
'get',
'make a get HTTP request',
function (yargs) {
return yargs.option('u', {
alias: 'url',
describe: 'the URL to make an HTTP request to'
})
},
function (argv) {
console.log(argv.url)
}
)
.help()
.argv

使用第三个接口需要把这个模块在单独的文件,然后用require引入

这是模块的代码

// my-module.js
exports.command = 'get <source> [proxy]' exports.describe = 'make a get HTTP request' exports.builder = {
banana: {
default: 'cool'
},
batman: {
default: 'sad'
}
} exports.handler = function (argv) {
// do something with argv.
}

引入的时候这样使用

yargs.command(require('my-module'))
.help()
.argv

当额外的模块没有定义cmd和desc的时候可以使用第二个接口

yargs.command('get <source> [proxy]', 'make a get HTTP request', require('my-module'))
.help()
.argv

这里建议使用第三个接口,这样能保持模块的内聚,这种模块你能挂载在任何命令下面,迁移的时候不需要修改模块代码,只需要修改引入模块的代码就能实现

.commandDir

如果有大量的命令都使用上面的.command(module)来开发的话,这些模块都有相同的结构,应该能有方法简化这些命令的引入过程,把这个过程自动化,基于

这个目的yargs提供了.commandDir接口

下面参考一个我自己写的项目pit

下面是这个项目的目录结构

.
├── pit
│   ├── douban
│   │   └── movie.js
│   ├── douban.js
│   ├── gg
│   │   ├── client.js
│   │   ├── login.js
│   │   ├── scope.js
│   │   ├── scope.json
│   │   ├── secret.json
│   │   ├── token.json
│   │   └── upload.js
│   ├── gg.js
│   ├── git
│   │   ├── commit.js
│   │   ├── create.js
│   │   ├── deploy.js
│   │   ├── push.js
│   │   └── token.json
│   ├── git.js
│   ├── gm.js
│   ├── md5.js
│   ├── news
│   │   ├── bing.js
│   │   ├── funs.js
│   │   ├── funs.json
│   │   ├── games.js
│   │   ├── games.json
│   │   ├── google.js
│   │   ├── newsall.json
│   │   ├── shops.js
│   │   ├── shops.json
│   │   ├── videos.js
│   │   └── videos.json
│   └── news.js
└── pit.js

pit.js:命令行的入口

#!/usr/bin/env node

require('yargs')
.commandDir('pit')
.demand(1)
.help()
.locale('en')
.showHelpOnFail(true, 'Specify --help for available options')
.argv

这段代码只指定读取同目录下同名文件夹pit下面的命令加载为子命令

注意:commandDir默认只会加载目录下第一级的文件,不会递归加载,如果想递归加载需要这样写.commandDir('pit', {recurse: true})

接着来看git子命令,因为git项目每次提交都要重复几个相同的步骤,所有想开发一个更简单的命令进行打包提交

git.js


exports.command = 'git <command>'; exports.desc = 'github command list'; exports.builder = function (yargs) {
return yargs.commandDir('git')
} exports.handler = function (argv) {}

git也是加载一个目录作为自己的子命令:以commit为例

commit.js

'use strict';

var fs = require('fs');
var path = require('path'); require('shelljs/global'); var Q = require('q'); function _exec(cmd) {
var deferred = Q.defer();
exec(cmd, function (code, stdout, stderr) {
deferred.resolve();
});
return deferred.promise;
} exports.command = 'commit'; exports.desc = 'commit repo local'; exports.builder = function (yargs) {
return yargs
.help('h');
}; exports.handler = function (argv) {
var repo = process.cwd();
var name = path.basename(repo);
Q.fcall(function () { })
.then(() => _exec(`git add .`))
.then(() => _exec(`git commit -m 'd'`))
.catch(function (err) {
console.log(err);
})
.done(() => {
console.log(`commit ${repo} done`);
}); }

这个命令默认运行在git项目的根目录,和git命令不太一样,git可以在项目根目录下的任意子目录里面运行。

使用shelljs来运行子命令,然后用Q进行promise封装,保证命令的执行顺序,同时把命令行输出和错误信息都打印到

控制。

一个很简单能节省时间的命令行程序,作为抛砖引玉之用

延伸

高手都是擅长使用命令行(电影里面的高手也一样),当你习惯使用命令行完成日常任务之后,慢慢的会形成一种依赖。继续下去,你会考虑把所有的事情都用来命令行来完成,当然这个

目的不能实现,因为能自动完成所有任务的命令行不叫命令行——它叫AI

虽然不能开发一台高智能ai,但是还是有很多任务能用命令行来完成的,这里写下我的思路,供大家参考

api命令行

大型网站都提供自己的api接口配上oauth2.0认证,如果你想使用命令行来调用这些api接口,你完全可以做到

像aws,google cloud,aliyun这种云主机,使用命令行能节省很多运维的时间

另外你也可以参考上面pit.js写的douban.js来抓取豆瓣的数据,豆瓣的公共api不需要认证就能访问,用来做一些测试非常方便

命令行爬虫

使用node.js开发爬虫就像使用python一样简单,但是一个功能齐全的爬虫必然少不了命令行接口,你不可能每次有新的需求都来修改代码,下次再给大家分享我写的一个简单的基于

node.js的爬虫项目

表单提交

对一些不提供api接口但是又想使用命令来进行交互的网站,你可以使用表单提交来进行登录,然后做一些登录之后才能做的事情:例如发表文章

现在很多的网站都支持使用markdown编辑文章,然后发布,对这一类网站你都可以开发自己的命令行统一进行管理,当你写完文章之后,只需要一个简单

的命令,就能把文章同时推送到各大网站

欢迎大家交流自己的想法!

从零开始打造个人专属命令行工具集——yargs完全指南的更多相关文章

  1. 基于node和npm的命令行工具——tive-cli

    前端开发过程中经常会用到各种各样的脚手架工具.npm全局工具包等命令行工具,如:Vue脚手架@vue/cli.React脚手架create-react-app.node进程守卫工具pm2.本地静态服务 ...

  2. 十分钟用 Node 命令行工具打造 react-cli 脚手架

    如果你有以下想法: 每次新开项目需要copy一堆文件/文件夹,太烦!想要快速建立工程 用了vue-cli.react-app,羡慕!想要自己做一个 你只需花十分钟时间,做一个Node命令行工具,打造属 ...

  3. windows下的命令行工具babun

    什么是babun babun是windows上的一个第三方shell,在这个shell上面你可以使用几乎所有linux,unix上面的命令,他几乎可以取代windows的shell.用官方的题目说就是 ...

  4. 命令行工具解析Crash文件&comma;dSYM文件进行符号化

    备份   文/爱掏蜂窝的熊(简书作者)原文链接:http://www.jianshu.com/p/0b6f5148dab8著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 序 在日常开发 ...

  5. 转:windows下命令行工具

    转自: http://www.cnblogs.com/haochuang/p/5593411.html Windows下CMD不好用,远没有Linux,或者一些SSH工具用起来方便.其实Windows ...

  6. JVM性能监控与故障处理命令行工具

    JDK命令行工具 Sun公司作为”礼物“赠送给JDK使用者的工具: 这些命令行工具大多是jdk/lib/tools.jar类库的一层薄包装,主要功能代码是在tools类库(不属于java的标准API) ...

  7. 10款Windows命令行工具

    Windows下CMD不好用,远没有Linux,或者一些SSH工具用起来方便.其实Windows下,也有一些不错的工具替代CMD: 0.powercmd经过比较,我最终选择了这款,这里补充一下截图:

  8. 微软开放技术发布针对 Mac 和 Linux 的更新版 Azure Node&period;JS SDK 和命令行工具

    发布于 2013-12-04 作者 Eduard Koller 这次为我们使用Linux 的朋友带来了更多关于部署云上虚拟机的消息.今天,微软开放技术有限公司 (MS Open Tech),想与大家分 ...

  9. 显示器 Linux 性能 18 &lpar;一个命令行工具传递&rpar;

    对于系统和网络管理员来说每天监控和调试Linux系统的性能问题是一项繁重的工作.在IT领域作为一名Linux系统的管理员工作5年后,我逐渐认识到监控和保持系统启动并执行是多么的不easy.基于此原因. ...

随机推荐

  1. Git命令之上传与同步

    操作步骤,可参考:http://blog.csdn.net/chenyufeng1991/article/details/47299461. 1.在本地仓库中,即项目目录下创建文件,如: 2.查看当前 ...

  2. python实现指定目录下批量文件的单词计数:串行版本

    直接上代码. 练习目标: 1.  使用 Python 面向对象的方法封装逻辑和表达 : 2.  使用异常处理和日志API : 3.  使用文件目录读写API : 4.  使用 list, map, t ...

  3. 标准盒模型与ie盒模型

    ff(标准的盒模型) Box的宽高包括 padding .border.margin.content区域 ie Box的宽度包括  margin  content区域(content区域包含paddi ...

  4. HDU 2673 shǎ崽 OrOrOrOrz

    #include <cstdio> #include <algorithm> using namespace std; int main() { int n; while (s ...

  5. 如何解决Ajax跨域问题-1

    如何解决Ajax跨域问题 最近在做AJAX调用C的问题,出现跨域问题,学习总结如下: 在做ajax读取数据的时候,经常会遇到ajax需要跨域的问题,但由于浏览器安全方面的限制,XMLHttpReque ...

  6. NIO SocketChannel 【链接】

    Java NIO系列教程(一) Java NIO 概述 Java NIO系列教程(六) Selector Java NIO系列教程(二) Channel Java NIO系列教程(三) Buffer ...

  7. OC Xcode中常见的错误

    在开发的过程中难免会遇到很多的错误,可是当看到系统给出的英文时,又不知道是什么意思.所以这篇文章总结了Xcode中常见的一些英文单词及词组,可以帮助初学的人快速了解给出的提示.多练习,就肯定能基本掌握 ...

  8. PHP------TP控制器

    TP控制器 打开  Home文件夹: 如果不想使用Index控制器,想新建一个自己使用的控制器,就可以在Controller文件夹下,新建一个文件(这个文件的命名规则,要按照控制器的命名规则来.第一个 ...

  9. tomcat 配置自签名ssl证书

    背景:据说17年苹果app必须走https协议与后台交互了,网上各种搜索最后还是发现有2篇写的比较全面,折腾后总结出2种实现方式.在这里记录,方便有共同需求的同学们参考 本文只介绍生成自签名ssl证书 ...

  10. The JVM found at JAVA&lowbar;HOME is damaged&period;Please reinstall or define EXE4J&lowbar;JAVA&lowbar;HOME to point to an installed 32-bit JDK or JRE

    一.介绍 exe4j是一个很棒的工具,可以把jar包打包成exe进行运行.他可以把jre环境和打包的exe进行集成,使得打包后的exe应用程序可以在没有安装java的机器上运行(前提是要把exe和jr ...