从标准输入读取所有文本到字符串
Read all text from stdin to a string
我正在 Node.js 中编写一个程序(在某些情况下)想要充当一个简单的过滤器:从标准输入读取所有内容(直到文件末尾),进行一些处理,写入结果到标准输出。
'read everything from stdin' 部分是怎么做的?到目前为止我找到的最接近的解决方案,似乎要么一次从控制台工作一行,要么只在标准输入是文件而不是管道时工作。
get-stdin 就可以了。
在您问题的字里行间读到一些注释。
既然你标记了问题 "synchronous",我只注意到标准输入在 node.js 中是异步的。上面的库是最简单的。它将整个输入作为字符串或缓冲区处理。
如果可能,最好以流式方式编写程序,但有些用例对于流式处理是可行的(即字数统计),而有些则不可行(即反转输入)。
此外,"one line at a time from the console" 是终端缓冲击键的产物。如果你想要一些 "I'm sorry I asked" 级别的详细信息,请查看令人惊叹的 the TTY Demystified.
如果您使用的是 linux,则不需要第三方软件包。当然,请考虑您的性能需求,但这两行将起作用:
const fs = require("fs");
const data = fs.readFileSync("/dev/stdin", "utf-8");
Jan 在下面的评论中指出,更便携的解决方案是使用 0
,因为这是 POSIX 标准。所以,你可以简单地使用:
const fs = require("fs");
const data = fs.readFileSync(0, "utf-8");
data
现在是一个包含来自标准输入的数据的字符串,解释为 utf 8
我在 Node 11+
中使用了以下内容
async function read(stream) {
const chunks = [];
for await (const chunk of stream) chunks.push(chunk);
return Buffer.concat(chunks).toString('utf8');
}
用法:
const input = await read(process.stdin);
我的这个样板很像上面评论中描述的解决方案——在顶层提供它,因为这是最简单的方法,不应该只在评论。
var fs = require('fs');
var data = fs.readFileSync(0, 'utf-8');
// Data now points to a buffer containing the file's contents
除了@Patrick Narkinsky 的解决方案,我在这里还没有看到实际同步的解决方案。但是 @Patrick Narkinsky 的回答不适用于 Windows。 似乎是一个 node.js 错误。如果你想了解细节,请随意进入这个 github 问题的兔子洞,但我在阅读一个小时后放弃了。
- https://github.com/aws/aws-cdk/issues/11314 此处报告的问题
- https://github.com/nodejs/node/issues/35997 该库的贡献者创建了一个节点问题
- https://github.com/libuv/libuv/pull/3053 一个 nodejs 贡献者提交了一个带有修复(?)(尚未合并)的 PR
我在那里找不到解决方法(我可能掩盖了它),但是 I accidentally stumbled on a solution to the problem. It's not pretty, but it works。由于那个 link 只显示了如何记录进度,我不得不根据自己的需要修改它:
import fs from 'fs';
const BUFSIZE = 256;
const buf = Buffer.alloc(BUFSIZE);
let bytesRead;
let stdin = '';
export function stdinToString(): string {
do {
// Loop as long as stdin input is available.
bytesRead = 0;
try {
bytesRead = fs.readSync(process.stdin.fd, buf, 0, BUFSIZE, null);
} catch (e) {
if (e.code === 'EAGAIN') {
// 'resource temporarily unavailable'
// Happens on OS X 10.8.3 (not Windows 7!), if there's no
// stdin input - typically when invoking a script without any
// input (for interactive stdin input).
// If you were to just continue, you'd create a tight loop.
throw 'ERROR: interactive stdin input not supported.';
} else if (e.code === 'EOF') {
// Happens on Windows 7, but not OS X 10.8.3:
// simply signals the end of *piped* stdin input.
break;
}
throw e; // unexpected exception
}
if (bytesRead === 0) {
// No more stdin input available.
// OS X 10.8.3: regardless of input method, this is how the end
// of input is signaled.
// Windows 7: this is how the end of input is signaled for
// *interactive* stdin input.
break;
}
// Process the chunk read.
stdin += buf.toString(undefined, 0, bytesRead);
} while (bytesRead > 0);
return stdin;
}
我已经编程十多年了,这是第一次 do while
让我的代码更干净 :) 没有它,如果不存在标准输入数据,这个函数就会挂起——有人可能会争辩说是 link.
代码中的错误
这回答了原始问题并且适用于所有操作系统。
我正在 Node.js 中编写一个程序(在某些情况下)想要充当一个简单的过滤器:从标准输入读取所有内容(直到文件末尾),进行一些处理,写入结果到标准输出。
'read everything from stdin' 部分是怎么做的?到目前为止我找到的最接近的解决方案,似乎要么一次从控制台工作一行,要么只在标准输入是文件而不是管道时工作。
get-stdin 就可以了。
在您问题的字里行间读到一些注释。
既然你标记了问题 "synchronous",我只注意到标准输入在 node.js 中是异步的。上面的库是最简单的。它将整个输入作为字符串或缓冲区处理。
如果可能,最好以流式方式编写程序,但有些用例对于流式处理是可行的(即字数统计),而有些则不可行(即反转输入)。
此外,"one line at a time from the console" 是终端缓冲击键的产物。如果你想要一些 "I'm sorry I asked" 级别的详细信息,请查看令人惊叹的 the TTY Demystified.
如果您使用的是 linux,则不需要第三方软件包。当然,请考虑您的性能需求,但这两行将起作用:
const fs = require("fs");
const data = fs.readFileSync("/dev/stdin", "utf-8");
Jan 在下面的评论中指出,更便携的解决方案是使用 0
,因为这是 POSIX 标准。所以,你可以简单地使用:
const fs = require("fs");
const data = fs.readFileSync(0, "utf-8");
data
现在是一个包含来自标准输入的数据的字符串,解释为 utf 8
我在 Node 11+
中使用了以下内容 async function read(stream) {
const chunks = [];
for await (const chunk of stream) chunks.push(chunk);
return Buffer.concat(chunks).toString('utf8');
}
用法:
const input = await read(process.stdin);
我的这个样板很像上面评论中描述的解决方案——在顶层提供它,因为这是最简单的方法,不应该只在评论。
var fs = require('fs');
var data = fs.readFileSync(0, 'utf-8');
// Data now points to a buffer containing the file's contents
除了@Patrick Narkinsky 的解决方案,我在这里还没有看到实际同步的解决方案。但是 @Patrick Narkinsky 的回答不适用于 Windows。 似乎是一个 node.js 错误。如果你想了解细节,请随意进入这个 github 问题的兔子洞,但我在阅读一个小时后放弃了。
- https://github.com/aws/aws-cdk/issues/11314 此处报告的问题
- https://github.com/nodejs/node/issues/35997 该库的贡献者创建了一个节点问题
- https://github.com/libuv/libuv/pull/3053 一个 nodejs 贡献者提交了一个带有修复(?)(尚未合并)的 PR
我在那里找不到解决方法(我可能掩盖了它),但是 I accidentally stumbled on a solution to the problem. It's not pretty, but it works。由于那个 link 只显示了如何记录进度,我不得不根据自己的需要修改它:
import fs from 'fs';
const BUFSIZE = 256;
const buf = Buffer.alloc(BUFSIZE);
let bytesRead;
let stdin = '';
export function stdinToString(): string {
do {
// Loop as long as stdin input is available.
bytesRead = 0;
try {
bytesRead = fs.readSync(process.stdin.fd, buf, 0, BUFSIZE, null);
} catch (e) {
if (e.code === 'EAGAIN') {
// 'resource temporarily unavailable'
// Happens on OS X 10.8.3 (not Windows 7!), if there's no
// stdin input - typically when invoking a script without any
// input (for interactive stdin input).
// If you were to just continue, you'd create a tight loop.
throw 'ERROR: interactive stdin input not supported.';
} else if (e.code === 'EOF') {
// Happens on Windows 7, but not OS X 10.8.3:
// simply signals the end of *piped* stdin input.
break;
}
throw e; // unexpected exception
}
if (bytesRead === 0) {
// No more stdin input available.
// OS X 10.8.3: regardless of input method, this is how the end
// of input is signaled.
// Windows 7: this is how the end of input is signaled for
// *interactive* stdin input.
break;
}
// Process the chunk read.
stdin += buf.toString(undefined, 0, bytesRead);
} while (bytesRead > 0);
return stdin;
}
我已经编程十多年了,这是第一次 do while
让我的代码更干净 :) 没有它,如果不存在标准输入数据,这个函数就会挂起——有人可能会争辩说是 link.
这回答了原始问题并且适用于所有操作系统。