[TOC]
## process.argv
process是node中的一個模塊,通過訪問process.argv我們能輕松愉快的接收通過命令執行node程序時候所傳入的參數。
>[info] argv翻譯成中文意思是:命令行變元數組。
這是什么意思呢?我們都在命令行窗口中使用過`npm`命令來進行包的下載,在使用npm命令的時候我們還能進行一些傳參,像要下載的包的名字啊,是開發依賴還是生產依賴啊。
這些所**傳的參數**+**node.exe絕對路徑**+**node所執行文件的絕對路徑**所組成的數組 = `process.argv`。它不止包含所傳的參數還包含另外兩個東東作為數組成員,故稱之為**變元**數組。
### 示例1
```
// 文件p1.js中
console.log(process.argv);
>>>命令行中輸入
node p1.js --a -b c
<<< 輸出
E:\w>node p1.js --a -b c
[ 'C:\\Program Files\\nodejs\\node.exe',
'E:\\w\\p1.js',
'--a',
'-b',
'c' ]
```
## 批處理文件
批處理文件,顧名思義,它能達到通過只執行一個文件從而執行多條node命令的效果,它能極大的簡化我們在命令行中的輸入,我們**只需要輸入批處理文件的名字,甚至不需要輸 `node`這個前綴**。
批處理文件在不同的操作系統下是不一樣的,主要分為:
- window下的批處理文件
- 類linux下的批處理文件
### windows中的批處理文件
windows中的批處理文件后綴名為`.bat`。
```
//hello.bat文件中
node p.js -a hello -b world
>>>命令行中
hello //為xx.bat文件去掉后綴的文件名
<<<輸出
[ 'C:\\Program Files\\nodejs\\node.exe',
'E:\\w\\p1.js',
'-a',
'hello',
'-b',
'world' ]
```
#### 占位符
在上面的栗子中有一個問題,我們所傳入的參數是固定的,要想它不固定,需要在.bat文件中使用占位符取代原本固定的參數,再在執行批處理文件時通過傳參進行映射。
```
//hello.bat文件中
node p.js %1 %2 %3 %4
>>>命令行中輸入
hello -a hello -b world //為xx.bat文件去掉后綴的文件名
<<<輸出
[ 'C:\\Program Files\\nodejs\\node.exe',
'E:\\w\\p1.js',
'-a',
'hello',
'-b',
'world' ]
```
[warning] **注意:**
- 此時%后面的數字代表了`%x`這個占位符代表是第幾個傳入的參數
- %x是從%1開始的而不是%0
上面雖然使傳參所傳入的參數值不再固定化了,但個數仍然是固定的,so我們推薦下面這種類linux的批處理文件。
### 類linx中的批處理文件
此時,我們不再需要`.bat`后綴名,我們的批處理文件名直接就是`xxx`(不再需要后綴)。
#### 給文件添加可執行權限
假若我們要執行的文件名為hello,要執行這個批處理文件,我們需要先給它添加可執行權限
```
$ chmod +x hello
```
#### 告訴命令行讓誰來執行這個文件里的內容
接著,在這個文件中添加一句話,意思是讓node來執行這個命令
```
#! /usr/bin/env node
```
#### './'執行文件
最后,如何執行這個文件呢,只需要訪問它即可
```
>>>輸入
$ ./hello --a -b c
<<< 輸出
[ 'C:\\Program Files\\nodejs\\node.exe',
'E:\\w\\hello',
'--a',
'-b',
'c' ]
```
[danger] **注意:** 此時`./`是必須的
#### npm link
如果我們想在輸入命令時不需要輸入前面的'./',我們就需要用到`npm link`了。
首先,在package.json下,添加這么一段
```
"bin":{
"hello":"hello" //前者為我們輸入的命令,后者為要執行的文件的路徑(包括文件名)
}
```
接著在package.json所處目錄下的命令行中輸入
```
npm link
```
這樣我們就無需在輸入命令時候還要加上`./`前綴,
[important]**注意:**
1. 這是因為npm link后,命令行中的命令指向了npm目錄bat文件(npm-link后會自動在npm目錄下生成,其作用是將package.json中我們所配置的那個可執行文件掛到這個.bat下),而 bat文件又指向了當前目錄 (package.json所處目錄)的hello文件(路徑)。
2. npm link必須配合#! /usr/bin/env node,否則windows會報腳本執行錯誤
## yargs
yargs能幫助我們在被執行的文件里所接受的參數進行包裝處理。
**yargs.argv就是包裝后的process.argv**,除此之外我們還能通過yargs.options對這個包裝對象再進行進一步的訂制。
[important] **注意:**
和process.argv很大的不同是它返回的是一個對象而不是數組,以**連詞線** `-` 或`--`開頭的參數會作為對象中的一個key值,而它后面的非連詞線開頭的參數會作為key的值,如果后面沒有非連詞線開頭的參數則會返回`true`
```
//hello文件中
#! /usr/bin/env node
let yargs = require('yargs');
let argv = yargs.argv; //.argv是必須的
console.log(argv);
>>>命令行中輸入
$ ./hello --a 1 -b 2 c
<<<輸出
{ _: [ 'c' ],
help: false,
version: false,
a: 1,
b: 2,
'$0': 'hello',}
console.log(argv.a);
<<<輸出
1
```
### 下劃線屬性
我們可以通過訪問`argv._`來獲取非連詞線開頭的參數
```
>>>命令行中輸入
$ ./hello d --a 1 -b 2 c
<<<輸出
[ 'd', 'c' ]
```
### 命令行參數的配置
多個不同參數的配置通過`.option`隔開
```
#! /usr/bin/env node
let yargs = require('yargs');
// let argv = yargs.argv;
let argv = yargs.options('a',{
alias:'ant'
,demand:true
,default:'super'
,describe:'一只灰常大的螞蟻'
,boolean:false
,type:'string'
}).options('b',{
alias:'BB'
,describe:'woshi bb'
,boolean:false
}).argv;
console.log(argv._);
console.log(argv);
>>>命令行中輸入
$ ./p1.js -a valueA -b valueB -c
<<<輸出
[]
{ _: [],
help: false,
version: false,
a: 'valueA',
ant: 'valueA',
b: 'valueB',
BB: 'valueB',
c: true,
'$0': 'p1.js' }
```
配置項說明:
- alias:別名,當傳入a時也會同時生成ant
- demand:該參數是否必須
- default:默認值
- describe:參數描述
- boolean:設置為true時,若該參數沒有傳入則會將該參數的值設置為false

- type:限制傳入參數的類型
### 配置幫助信息
首先yargs已經默認為我們提供了`--help`參數來顯示幫助信息,我們同樣的,可以給這個--help參數配置個別名來簡化
```
let argv = yargs.此處省略一萬字.help('h').argv
>>>命令行中輸入
$ ./p1.js --h
<<<輸出
選項:
--version 顯示版本號 [布爾]
-a, --ant 一只灰常大的螞蟻 [字符串] [必需] [默認值: "super"]
-b, --BB woshi bb [布爾]
-h 顯示幫助信息 [布爾]
```
配置其它的幫助提示
- usage:用法格式
- example:一個詳細的使用栗子
- epilog:結尾處的顯示,常用來顯示命令工具的版本行
```
// hello文件中
...
.help('h')
.usage('hello -[option] value')
.example('我,栗子,讓你明白!')
.epilog('copyright 2018-')
.argv;
>>>
$ ./hello -h
<<<
hello -[option] value
選項:
--version 顯示版本號 [布爾]
-a, --ant 一只灰常大的螞蟻 [字符串] [必需] [默認值: "super"]
-b, --BB woshi bb [布爾]
-h 顯示幫助信息 [布爾]
示例:
我,栗子,讓你明白!
copyright 2018-
```
### yargs實現思路
```
let args = process.argv;
let argv = {};
for(let i=2;i<args.length;++i){
let cur = args[i];
if(/^(--)/.test(cur)){
argv[cur.slice(2)] = args[++i];
}
}
```