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

如何在Makefile中使用tput实现终端全宽分隔线格式化输出?

在Makefile中用tput生成全宽分隔线的解决方法

你遇到的问题核心是Makefile的变量展开顺序和shell命令转义的问题。原命令里的$(tput cols)会被Make优先解析,而不是留给shell执行,这就导致要么拿到的是Make进程启动时的终端尺寸(甚至可能是空值),要么直接解析出错,最终输出空行。

下面是两种可行的解决方案:

方案一:动态获取当前终端宽度(推荐)

这个方法会在每次执行目标时,让shell实时获取终端宽度,适配窗口大小变化:

lineTest:
	@echo "$$(printf '%*s' "$${COLUMNS:-$$(tput cols)}" '' | tr ' ' –)"

关键转义解释:

  • $$(printf):Make会把$$解析成单个$传递给shell,所以shell实际执行的是$(printf)命令。
  • "$${COLUMNS:-$$(tput cols)}":
    • $${COLUMNS}:让Make传递${COLUMNS}给shell,shell会读取环境变量中的终端宽度。
    • $$(tput cols):Make转义后,shell看到的是$(tput cols),会执行该命令获取终端宽度(当COLUMNS变量不存在时生效)。
  • 双引号包裹整个命令结果:避免shell对输出内容做不必要的拆分。

如果要兼容非交互式环境(比如CI流水线,tput可能无法获取终端尺寸),可以加个默认值:

lineTest:
	@echo "$$(printf '%*s' "$${COLUMNS:-$$(tput cols 2>/dev/null || echo 80)}" '' | tr ' ' –)"

方案二:提前获取终端宽度(静态)

如果不需要适配窗口大小变化,可以在Makefile解析阶段就获取终端宽度,之后复用这个值:

# 在Makefile解析时获取终端宽度,仅执行一次
TERM_COLS := $(shell tput cols 2>/dev/null || echo 80)

lineTest:
	@echo "$$(printf '%*s' "$(TERM_COLS)" '' | tr ' ' –)"

这个方法的缺点是,如果用户在Makefile解析后调整了终端窗口大小,分隔线宽度不会更新。

测试验证

保存上述Makefile后,执行make lineTest,就能看到横跨终端全宽的分隔线了。

内容的提问来源于stack exchange,提问作者Audun Olsen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:31:17