Node.js:无需尾随换行符即可打印到控制台?


681

是否有一种无需尾随换行符即可打印到控制台的方法?该console对象的文档并没有说关于任何东西:

console.log()

用换行符打印到标准输出。该函数可以采用类似printf()的方式接受多个参数。例:

console.log('count: %d', count);

如果在第一个字符串中找不到格式设置元素,则util.inspect在每个参数上使用格式设置元素。

Answers:


1054

您可以使用process.stdout.write()

process.stdout.write("hello: ");

有关详细信息,请参阅文档


7
这为我解决了相反的问题。console.log在打印时\n从字面上时,我想它打印一个换行符。
保罗

@Paulpro不是'\ n'换行符吗?
亚历山大·米尔斯

3
@AlexMills这是换行符的转义序列,但它本身不是换行符。` followed by an 当我想输出一个真正的换行符时,我得到了一个文字n`。
保罗

377

另外,如果要覆盖同一行中的消息(例如,在倒计时中),则可以在字符串的末尾添加“ \ r”。

process.stdout.write("Downloading " + data.length + " bytes\r");

18
尽管这不是问题的答案,但这是一个了不起的答案。等不及要尝试了。
隆达

8
这并不会在Windows上为我工作。但是在非母猪上效果很好。
chowey

45
对于Windows,您可以使用等效代码'\ 033 [0G',例如:process.stdout.write("Downloading " + data.length + " bytes\033[0G");
GarciadelCastillo 2014年

19
要使@GarciadelCastillo的注释中给出的ansi转义代码在严格模式下工作,请\033用十六进制文字替换八进制文字,\x1b如下所示:\x1b[0G。(适用于严格代码和非严格代码)
大约

7
只需将\ r放在字符串的开头而不是结尾,即可在Windows中使用。
daremkd

20

在Windows控制台(也是Linux)中,您应该'\r'用其等效代码替换\033[0G

process.stdout.write('ok\033[0G');

这使用VT220终端转义序列将光标发送到第一列。


1
您将如何备份多行而不是仅备份当前行?该顶部程序似乎能够覆盖我的整个缓冲区,而它的运行和恢复什么在那里,当它完成。有人知道这是怎么做的吗?i.imgur.com/AtCmEjn.gif
Chev

我相信它可能会使用其中之一: github.com/mscdex/node-ncurses github.com/chjj/blessed
Brandon

1
它可以正常工作,但是我得到的光标也一样[\] 39,并且光标在第一个字符上突出显示:var spinner = '|/-\\'.split('');process.stdout.write("["+this.randomElement(spinner)+"] "+message+"\033[0G");
loretoparisi

1
@Chev Top很特殊,不是您可以使用ANSI转义代码编写的东西。它,实际上,使用ncurses的这就是为什么你不会发现它不具备大型C库嵌入式系统

1
@Chev:由于他们自己的FUD,大多数人会劝阻您不要使用硬编码的转义序列,但是现在几乎每个人都使用VT100,因此兼容性不再是真正的问题。您所指的功能是“备用屏幕”行为。可以在man console_codes(Linux或在线)上找到基本的介绍,我最喜欢的参考资料是www2.phys.canterbury.ac.nz/dept/docs/manuals/unix/DEC_4.0e_Docs/…(其中99%的内容仍然有效) 。仅警告:准备广泛部署之前,准备在几个不同的终端上测试任何实验。
i336_

18

为了扩展/增强上述@rodowi关于可以覆盖一行的出色补充:

process.stdout.write("Downloading " + data.length + " bytes\r");

如我在代码中所见,如果您不希望终端光标位于第一个字符处,请考虑执行以下操作:

let dots = ''
process.stdout.write(`Loading `)

let tmrID = setInterval(() => {
  dots += '.'
  process.stdout.write(`\rLoading ${dots}`)
}, 1000)

setTimeout(() => {
  clearInterval(tmrID)
  console.log(`\rLoaded in [3500 ms]`)
}, 3500)

通过\r在下一个打印语句的前面放置光标,将在替换字符串覆盖前一个字符串之前重置光标。


13

util.print也可以使用。阅读:http : //nodejs.org/api/util.html#util_util_print

util.print([...])#同步输出函数。将阻塞该过程,将每个参数转换为字符串,然后输出到stdout。不要在每个参数后面放置换行符。

一个例子:

// get total length
var len = parseInt(response.headers['content-length'], 10);
var cur = 0;

// handle the response
response.on('data', function(chunk) {
  cur += chunk.length;
  util.print("Downloading " + (100.0 * cur / len).toFixed(2) + "% " + cur + " bytes\r");
});

39
util.print现在已弃用
Petr Peller

(node:7616) DeprecationWarning: util.print is deprecated. Use console.log instead.
格林

10

似乎有许多答案表明:

process.stdout.write

错误日志应发布在:

process.stderr

而是使用:

console.error

对于任何想知道为什么process.stdout.write('\033[0G');不执行任何操作的人,因为它stdout被缓冲了,您需要等待drain事件(更多信息)。

如果写返回false,将触发一个drain事件。


4

这些解决方案均不适用于我,process.stdout.write('ok\033[0G')仅使用它'\r'即可创建新行,而不会在Mac OSX 10.9.2上覆盖。

编辑: 我不得不用它来替换当前行:

process.stdout.write('\033[0G');
process.stdout.write('newstuff');

4

使用严格模式时出现以下错误:

节点错误:“严格模式下不允许使用八进制文字。”

以下解决方案有效(来源):

process.stdout.write("received: " + bytesReceived + "\x1B[0G");

更改八进制文字tobsone.orher的数字格式
FrancescoMM
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.