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

如何实现可重复调用的实时缩进Bash管道函数?

问题描述

需要实现一个满足以下要求的Bash函数:

  • 可通过管道调用,如 echo input | my_function
  • 为每行输入添加开头缩进(制表符\t)
  • 支持重复调用实现多级缩进,例如 echo input | my_function | my_function 输出 \t\tinput
  • 无需等待全部输入完成,可实时逐行输出

测试脚本如下:

#!/usr/bin/env bash

main() {
  echo 'first:'
  echo 'once' | tab_indent_to_right
  echo 'twice' | tab_indent_to_right | tab_indent_to_right
  {
    echo 'wait 2 sec'
    sleep 2
    echo 'wait 2 sec'
    sleep 2
    echo 'waited'
  } | tab_indent_to_right
}

tab_indent_to_right() {
  # while read -r line; do echo $'\t'"$line"; done  # 🔴 无法实现双重缩进
  # awk -v prefix='\t' '{print prefix $0}'          # 🔴 存在缓冲问题
  # sed 's/^/\t/'                                   # 🔴 存在缓冲问题
  # xargs -I {} echo $'\t{}'                        # 🔴 无法实现双重缩进
  # xargs -L1 echo $'\t'                            # 🔴 无法实现双重缩进
}

main

现有尝试方案存在两类问题:

  • 无法实现重复调用的多级缩进:部分写法在管道串联时无法累积缩进效果
  • 存在输出缓冲:需等待所有输入生成完毕(如sleep执行完成)才批量输出,无法实时逐行打印

解决方案

修改tab_indent_to_right函数为以下实现即可满足所有需求:

tab_indent_to_right() {
  while IFS= read -r line || [[ -n "$line" ]]; do
    printf '\t%s\n' "$line"
  done
}

方案说明:

  1. 支持多级缩进:
    每次调用函数都会为当前输入的每一行开头添加一个制表符,当通过管道串联调用时,前一次函数输出的已缩进内容会作为下一次函数的输入,自然累积生成多级缩进(两次调用就会添加两个\t)。

  2. 实时逐行输出:

    • while read -r line会逐行读取输入流,每读取一行就立即处理并输出,不存在批量缓冲延迟;
    • 使用printf替代echo,避免echo对特殊字符的潜在处理问题,同时保证输出格式的一致性;
    • IFS= read -r line的写法可以保留输入行开头和结尾的空格,且避免read将反斜杠解析为转义字符;|| [[ -n "$line" ]]则能处理输入最后一行没有换行符的情况,确保所有内容都被正确处理。

运行修改后的测试脚本,即可看到符合预期的输出:

  • echo 'once' | tab_indent_to_right 输出 \tonce
  • echo 'twice' | tab_indent_to_right | tab_indent_to_right 输出 \t\ttwice
  • 带sleep的代码块会实时逐行输出:先打印\twait 2 sec,等待2秒后打印\twait 2 sec,再等待2秒后打印\twaited

内容的提问来源于stack exchange,提问作者U. Bulle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 14:30:16