NodeJS學習筆記 (25)逐行讀取-readline(ok)


模塊概覽

readline是個非常實用的模塊。如名字所示,主要用來實現逐行讀取,比如讀取用戶輸入,或者讀取文件內容。常見使用場景有下面幾種,本文會逐一舉例說明。

  • 文件逐行讀取:比如說進行日志分析。
  • 自動完成:比如輸入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 "http://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 "http://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 "http://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],訪問地址:"http://www.example.com/oc/v/account/login.html" 訪問時間:[2016-12-09 14:00:10.618],訪問地址:"http://www.example.com/oc/v/account/user.html" 訪問時間:[2016-12-09 14:00:34.200],訪問地址:"http://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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM