逐行读取-readline
// readline 是非常实用的模块,主要用来实现逐行读取,比如读取用户输入,或者读取文件内容,常用的场景包括
// 1. 文件逐行读取,比如说进行日志分析
// 2. 自定完成,比如输入npm,自动提示 help init install
// 3. 命令行工具,比如 npm init 这种问答式的脚手架工具
基础例子
// 要求用户输入一个简答的单子,然后自动转成大写
const ls = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
ls.question("请输入一个字母", (answer) => {
console.log("你输入了 [%s]", answer.toUpperCase());
ls.close();
});
// 请输入一个字母a
// a
// 你输入了 [A]
例子:文件逐行读取,日志分支
// 比如有如下日志, 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 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]);
});
// 访问时间: [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
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 (subCommands) {
const aa = line.replace(command, "").trim();
return aa && subCommands.indexOf(aa) > -1;
});
if (hits.length === 1) {
hits = hits.map((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();
// PS D:\Node-learning\nodejs-learning-guide-master\practice\readline> node .\index.js
// > npm inhits--> [ 'init', 'install' ]
// > inshits--> [ 'install' ]
// > npm install
例子: 命令行工具 npm init
// 下面借助 readline 实现一个迷你版 npm init功能,运行脚本时,会一次要求用户输入name version author属性
// 这里用到的是 rl.question(msg,cbk) 这个方法,他会在控制台输入一行提示,当用户输入完成,敲击回车,cbk就会被调用,并把用户输入作为参数传入
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: "OHA> ",
});
const preHint = `
这个实用程序将引导您创建一个package.json文件。
它只涵盖了最常见的项目,并试图猜测合理的默认值。
有关这些字段的最终文档,请参阅“npm help json”
以及他们到底在做什么。
之后使用\`npm-install<pkg>--save\`安装软件包并
将其作为依赖项保存在package.json文件中。
随时按^C退出。
`;
console.log(preHint);
let questions = ["name", "version", "author"];
let defaultAnswers = ["LGQ", "1.0.0", "none"];
let answers = [];
let index = 0;
function createPackageJson() {
let map = {};
questions.forEach((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) {
console.log("answer--->", answer);
// 把输入的答案存起来
answers.push(answer || defaultAnswer);
// 进入下一个问题
index++;
runQuestionLoop();
});
}
runQuestionLoop();
写在后面
// 有不少基于readline的有趣的工具,比如各种脚手架工具。限于篇幅不展开,感兴趣的同学可以研究下。
相关链接
// https://nodejs.org/api/readline.html