node.js - 为什么我不能通过管道 npm install 到 sed,同时保留颜色和进度更新?

标签 node.js bash sed npm npm-install

如果我输入 npm i | sed "s/^/ /" ,输出npm i打印到标准输出时没有间隔。例如。我得到以下信息:

$ npm i | sed "s/^/    /"
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.0.0 
(node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for 
fsevents@1.1.2: wanted {"os":"darwin","arch":"any"} (current: 
{"os":"linux","arch":"x64"})
npm WARN [name_removed]@0.0.2 No repository field.
npm WARN [name_removed]@0.0.2 No license field.

而不是:

$ npm i | sed "s/^/    /"
    npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.0.0 
    (node_modules/chokidar/node_modules/fsevents):
    npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for 
    fsevents@1.1.2: wanted {"os":"darwin","arch":"any"} (current: 
    {"os":"linux","arch":"x64"})
    npm WARN [name_removed]@0.0.2 No repository field.
    npm WARN [name_removed]@0.0.2 No license field.

编辑: 警告将发送到 stderr(呃...),所以我需要使用 npm i 2>&1 | sed 's/^/ / ,但这会从输出中删除颜色,并且我看不到进度条,您可以在下面的 gif 中看到。

enter image description here enter image description here

编辑2:颜色通过 npm i --color=always | sed 's/^/ / 固定,但我仍然看不到进度条。此外,它似乎在所有输出后面的行中添加了行...我认为这是由输出的颜色代码引起的?您可以在下面的 gif 中看到这种现象:

enter image description here

当前状态: enter image description here

最佳答案

您在这里遇到了几个问题,其中大多数与 npm 的方式有关。处理其输出。

捕获警告

首先请注意 npm stderr 上输出警告并更新进度 ,而只有最终结果会转到 stdout 。因此,为了处理警告,您必须重定向 stderrstdout像这样的东西:

npm install 2>&1 | sed 's/^/    /'

保留颜色

但现在有了 stderr通过管道发送到sed过程中,你会注意到npm省略着色!然而,这是大多数命令行工具的标准行为(例如 lsgrep 等)。仅当输出到 TTY 时,它们才会输出 ANSI 转义(颜色)序列。设备(即用户,而不是文件或管道)。确定文件描述符是否连接到 TTY 的常用方法通过 isatty(int fd) 功能。事实证明 ( after some digging ) npm使用相同的机制。

要解决着色问题,我们有两种选择:

(1) 我们可以使用 --color=always 强制颜色输出选项(类似于 lsgrep 等):

npm install --color=always 2>&1 | sed 's/^/    /'

或者,(2)我们可以使用名为 script 的工具这将伪造 TTY任何程序/脚本运行的输出设备:

script -feqc 'npm install' /dev/null | sed 's/^/    /'

请注意,我们不必重定向 stderrstdout不再了,script为我们做到这一点。另外,script会将完整的输出保存到我​​们选择的文件中(在本例中我们不需要它,所以我们说 /dev/null )。 (顺便说一句,-f 将在每次写入后刷新输出,-e 将确保命令的退出代码返回到父级/shell,-q 强制安静模式,没有信息消息,并且使用 -c cmd 我们提供要运行的命令。)

保留进度更新

好的,现在我们已经缩进了警告并保留了颜色,但是我们丢失了进度(栏)更新!

为什么会发生这种情况?嗯,因为npm在一行中输出完整的进度。每次进度更新时,它将移动到字符位置零(同一行!)并打印新进度。对于 sed完整的进度只是一行,并且从sed开始是面向行的,它会等到行尾( \n )再进行任何处理(和输出)。

显然,我们需要降低一级 - 逐个字符地进行处理。为了达到缩进的效果,我们将替换每个出现的 \n\n<4 spaces> .

通常,对于字符翻译,我们可以使用 tr ,但这里我们需要的不止这些,因为在某些情况下( \n )我们需要将一个字符扩展到多个字符。一种方法是使用这个简单的 bash脚本/函数:

#!/bin/bash
# read each character of stdin, indenting each line
interactive_indent() {
    local space='    '
    echo -n "$space"
    while IFS= read -r -d '' -n1 chr; do
        [[ $chr == $'\n' ]] && chr="\\n\\r$space"
        [[ $chr == $'\r' ]] && chr="\\r$space"
        echo -ne "$chr"
    done
    echo -ne '\r'
}

例如:

$ echo -e 'one\ntwo\rthree' | interactive_indent
    one
    three

最后,我们找到了交互式 npm 的解决方案流程:

script -feqc 'npm install' /dev/null | interactive_indent

这将传递每个字符(显示进度),同时缩进每行(在 \n\r 之后)。

请注意我们的interactive_indent函数比简单的 \n 稍微复杂一些-到- \n<spaces>替代者。我们还必须处理 \r 大量使用的回车符 ( npm )对于进度更新和依赖关系树绘制,并确保每个新行从位置零开始(因此 \r 与每个 \n 旁边)。

关于node.js - 为什么我不能通过管道 npm install 到 sed,同时保留颜色和进度更新?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46493608/

相关文章:

node.js - Google Cloud Endpoints 等同于 API 网关,还是 Endpoints 等同于微服务?

shell - 在 sed 命令中使用日期变量

perl - 使用自定义实用程序进行搜索和替换以进行转换

javascript - 如何使用来自客户端的 Socket IO to(-).emit(-) 消息(Javascript)

node.js - 类型错误: Cannot read property 'path' of undefined in Mongoose 4. 0.3

linux - 即时更改 AWK 字段分隔符

bash - 使用 xargs 作为 cut 的参数

perl -pe one liner : Replace all matched characters with same number of a different character. 非全局

linux - 如何通过 linux apache 服务器在浏览器上运行 node.js?

linux - 使用shell脚本将json文件转换为csv而不使用jq?