Won*_*Boi 1 bash sed node.js 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.
Run Code Online (Sandbox Code Playgroud)
代替:
$ 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.
Run Code Online (Sandbox Code Playgroud)
编辑:警告将发送到标准错误(废话...),所以我需要使用npm i 2>&1 | sed 's/^/ /,但这会从输出中删除颜色,我没有看到进度条,您可以在下面的 gif 中看到。
Edit2:颜色通过 固定npm i --color=always | sed 's/^/ /,但我仍然看不到进度条。此外,它似乎在所有输出之后的行中添加了几行……我认为这是由输出颜色代码引起的?您可以在下面的 gif 中看到这种现象:
您在这里遇到了几个问题,其中大部分与npm处理其输出的方式有关。
注意:第一,npm产出警告和更新进度上stderr,而只有最后的结果去stdout。因此,为了处理警告,您必须使用以下内容重定向stderr到stdout:
npm install 2>&1 | sed 's/^/ /'
Run Code Online (Sandbox Code Playgroud)
但是现在使用stderr管道进行sed处理,您会注意到npm省略了着色!然而,这是大多数命令行工具(像一个标准的行为ls,grep等等)。只有当输出到TTY设备(即用户,而不是文件或管道)时,它们才会输出 ANSI 转义(颜色)序列。确定文件描述符是否连接到 a 的常用方法TTY是通过isatty(int fd)函数。事实证明(经过 一些 挖掘)npm正在使用相同的机制。
要解决着色问题,我们有两种选择:
(1)我们可以强制与彩色输出--color=always选项(类似于ls,grep和其他人):
npm install --color=always 2>&1 | sed 's/^/ /'
Run Code Online (Sandbox Code Playgroud)
或者,(2)我们可以使用一个名为的工具script,它可以为任何程序/脚本运行伪造一个TTY输出设备:
script -feqc 'npm install' /dev/null | sed 's/^/ /'
Run Code Online (Sandbox Code Playgroud)
请注意,我们不必再重定向stderr到stdout,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'
}
Run Code Online (Sandbox Code Playgroud)
例如:
$ echo -e 'one\ntwo\rthree' | interactive_indent
one
three
Run Code Online (Sandbox Code Playgroud)
最后,我们来到我们交互npm过程的解决方案:
script -feqc 'npm install' /dev/null | interactive_indent
Run Code Online (Sandbox Code Playgroud)
这将传递每个字符(显示进度),同时缩进每一行(在\n或之后\r)。
请注意,我们的interactive_indent函数比简单的\n替换器稍微复杂一些\n<spaces>。我们还必须处理在进度更新和依赖树绘制\r中大量使用的回车 ( ) npm,并确保每个新行从位置零开始(因此\r与 each 并列\n)。