You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写可通过管道调用的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 解析,是终端直接负责解析的,不生效通常是两个原因:

  1. 运行在不支持 ANSI 转义序列的终端环境,比如 Windows 旧版 cmd/powershell,需要手动开启 VT100 支持或者切换到 Windows Terminal
  2. 输出目标不是终端(比如管道到文件、其他程序),部分环境会自动禁用转义序列解析

优化后的 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 17:54:03