如何编写可通过管道调用的shell函数实现命令输出文本标红?
Shell 版本修复方案
原 shell 函数丢失缩进的核心原因有两个:
read命令默认会忽略首尾空白字符,同时会将连续空白视为分隔符,直接吃掉缩进- 输出
$text时没有用双引号包裹,shell 会将变量内的连续空白合并为单个空格
修复后的逐行实现
red() { # 清空IFS避免read截断空白,加-r参数避免read转义内容中的反斜杠 while IFS= read -r text do # 变量用双引号包裹保留原有格式 echo -e "\033[31m${text}\033[0m" done # 兼容处理最后一行没有换行符的场景 if [[ -n $text ]]; then echo -e "\033[31m${text}\033[0m" fi }
更高效的 sed 实现(推荐)
不需要逐行循环,性能更好,同时自动兼容所有原有格式:
red() { # 先替换原有内容里的颜色重置符,避免红色被中断,再给每行加前后颜色标记 sed -e 's/\x1b\[0m/\x1b[0m\x1b[31m/g' -e 's/^/\x1b[31m/' -e 's/$/\x1b[0m/' }
C 程序问题修复
原 C 代码逻辑本身没有错误,ANSI 转义码不需要 shell 解析,是终端直接负责解析的,不生效通常是两个原因:
- 运行在不支持 ANSI 转义序列的终端环境,比如 Windows 旧版 cmd/powershell,需要手动开启 VT100 支持或者切换到 Windows Terminal
- 输出目标不是终端(比如管道到文件、其他程序),部分环境会自动禁用转义序列解析
优化后的 C 实现
支持实时输出(不需要等全部输入读完才输出),同时自动判断输出目标是否为终端,避免非终端场景输出乱码:
#include <stdio.h> #include <unistd.h> int main() { int c; int is_tty = isatty(STDOUT_FILENO); // 仅输出到终端时添加红色前缀 if (is_tty) printf("\033[31m"); while ((c = getchar()) != EOF) { // 遇到原输出的颜色重置符时,重置后重新开启红色 if (c == '\033') { putchar(c); while ((c = getchar()) != EOF && c != 'm') { putchar(c); } if (c == 'm' && is_tty) { putchar(c); printf("\033[31m"); continue; } if (c == EOF) break; } putchar(c); } // 仅输出到终端时添加颜色重置后缀 if (is_tty) printf("\033[0m"); fflush(stdout); return 0; }
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

