Nodejs進階:readline實現日誌分析+簡易命令行工具
本文摘錄自《Nodejs學習筆記》,更多章節及更新,請訪問 github主頁地址。歡迎加群交流,群號 197339705。
模塊概覽
readline是個非常實用的模塊。如名字所示,主要用來實現逐行讀取,比如讀取用戶輸入,或者讀取文件內容。常見使用場景有下麵幾種,本文會逐一舉例說明。本文相關代碼可在筆者github上找到。
- 文件逐行讀取:比如說進行日誌分析。
- 自動完成:比如輸入npm,自動提示"help init install"。
- 命令行工具:比如npm init這種問答式的腳手架工具。
基礎例子
先看個簡單的例子,要求用戶輸入一個單詞,然後自動轉成大寫
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('Please input a word: ', function(answer){
console.log('You have entered {%s}', answer.toUpperCase());
rl.close();
});
運行如下:
toUpperCase git:(master) node app.js
Please input a word: hello
You have entered {HELLO}
例子:文件逐行讀取:日誌分析
比如我們有如下日誌文件access.log,我們想要提取“訪問時間+訪問地址”,借助readline
可以很方便的完成日誌分析的工作。
[2016-12-09 13:56:48.407] [INFO] access - ::ffff:127.0.0.1 - - "GET /oc/v/account/user.html HTTP/1.1" 200 213125 "https://www.example.com/oc/v/account/login.html" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36"
[2016-12-09 14:00:10.618] [INFO] access - ::ffff:127.0.0.1 - - "GET /oc/v/contract/underlying.html HTTP/1.1" 200 216376 "https://www.example.com/oc/v/account/user.html" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36"
[2016-12-09 14:00:34.200] [INFO] access - ::ffff:127.0.0.1 - - "GET /oc/v/contract/underlying.html HTTP/1.1" 200 216376 "https://www.example.com/oc/v/account/user.html" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36"
代碼如下:
const readline = require('readline');
const fs = require('fs');
const rl = readline.createInterface({
input: fs.createReadStream('./access.log')
});
rl.on('line', (line) => {
const arr = line.split(' ');
console.log('訪問時間:%s %s,訪問地址:%s', arr[0], arr[1], arr[13]);
});
運行結果如下:
lineByLineFromFile git:(master) node app.js
訪問時間:[2016-12-09 13:56:48.407],訪問地址:"https://www.example.com/oc/v/account/login.html"
訪問時間:[2016-12-09 14:00:10.618],訪問地址:"https://www.example.com/oc/v/account/user.html"
訪問時間:[2016-12-09 14:00:34.200],訪問地址:"https://www.example.com/oc/v/account/user.html"
例子:自動完成:代碼提示
這裏我們實現一個簡單的自動完成功能,當用戶輸入npm時,按tab鍵,自動提示用戶可選的子命令,如help、init、install。
- 輸入
np
,按下tab:自動補全為npm - 輸入
npm in
,按下tab:自動提示可選子命令 init、install - 輸入
npm inst
,按下tab:自動補全為npm install
const readline = require('readline');
const fs = require('fs');
function completer(line) {
const command = 'npm';
const subCommands = ['help', 'init', 'install'];
// 輸入為空,或者為npm的一部分,則tab補全為npm
if(line.length < command.length){
return [command.indexOf(line) === 0 ? [command] : [], line];
}
// 輸入 npm,tab提示 help init install
// 輸入 npm in,tab提示 init install
let hits = subCommands.filter(function(subCommand){
const lineTrippedCommand = line.replace(command, '').trim();
return lineTrippedCommand && subCommand.indexOf( lineTrippedCommand ) === 0;
})
if(hits.length === 1){
hits = hits.map(function(hit){
return [command, hit].join(' ');
});
}
return [hits.length ? hits : subCommands, line];
}
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
completer: completer
});
rl.prompt();
代碼運行效果如下,當輸入npm in
,按下tab鍵,則會自動提示可選子命令init、install。
autoComplete git:(master) node app.js
> npm in
init install
例子:命令行工具:npmt init
下麵借助readline實現一個迷你版的npm init
功能,運行腳本時,會依次要求用戶輸入name、version、author屬性(其他略過)。
這裏用到的是rl.question(msg, cbk)
這個方法,它會在控製台輸入一行提示,當用戶完成輸入,敲擊回車,cbk
就會被調用,並把用戶輸入作為參數傳入。
const readline = require('readline');
const fs = require('fs');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: 'OHAI> '
});
const preHint = `
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See \`npm help json\` for definitive documentation on these fields
and exactly what they do.
Use \`npm install <pkg> --save\` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
`;
console.log(preHint);
// 問題
let questions = [ 'name', 'version', 'author'];
// 默認答案
let defaultAnswers = [ 'name', '1.0.0', 'none' ];
// 用戶答案
let answers = [];
let index = 0;
function createPackageJson(){
var map = {};
questions.forEach(function(question, index){
map[question] = answers[index];
});
fs.writeFileSync('./package.json', JSON.stringify(map, null, 4));
}
function runQuestionLoop() {
if(index === questions.length) {
createPackageJson();
rl.close();
return;
}
let defaultAnswer = defaultAnswers[index];
let question = questions[index] + ': (' + defaultAnswer +') ';
rl.question(question, function(answer){
answers.push(answer || defaultAnswer);
index++;
runQuestionLoop();
});
}
runQuestionLoop();
運行效果如下,最後還像模像樣的生成了package.json(害羞臉)。
commandLine git:(master) node app.js
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See `npm help json` for definitive documentation on these fields
and exactly what they do.
Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
name: (name) hello
version: (1.0.0) 0.0.1
author: (none) chyingp
寫在後麵
有不少基於readline的有趣的工具,比如各種腳手架工具。限於篇幅不展開,感興趣的同學可以研究下。
相關鏈接
https://nodejs.org/api/readline.html
最後更新:2017-05-05 11:31:39