交互地使用 bash 我尝试使用 cut 来防止行长度超过我的终端宽度。但是,当使用带有彩色输出的命令时,所有颜色都会被剪切删除。例如: ls -lG | cut -c 1-$COLUMNS
。
有没有什么方法可以剪切并保留颜色格式?
答案1
你这里有两个问题
ls -G
当输出未到达终端(此处为管道)时,停止以颜色输出。 GNUls
需要传递一个--color=always
选项,对于 BSDls
,您需要将环境设置CLICOLOR_FORCE
为非空值以告诉它始终以颜色输出。颜色是通过输出转义序列来实现的,转义序列是字符序列,例如
<ESC>[1;31m
前景粗体红色。显示时没有任何宽度,但就其而言cut
,它是 7 个字节或字符,最多可达$COLUMNS
。所以你不能
cut
在这里使用,因为你需要忽略计算中的那些转义序列。相反,你可以这样做:esc=$'\e' # or esc=$(printf '\33') if your shell doesn't do $'...' CLICOLOR_FORCE=1 ls -l | sed " s/^\(\(\($esc\[[0-9;]*m\)*.\{0,1\}\)\{$COLUMNS\}\).*/\1${esc}[m/"
在那里,
sed
进行计数并添加一个\e[m
以将颜色恢复为默认值,以防颜色在过程中被剪切。请注意,虽然它处理多字节单宽字符(与
cut
当前版本的 GNU 实现-c
相反-b
),但它不处理零宽度或双宽度字符,也不处理制表或其他控制字符。
或者,您可以告诉您的终端不要换行并自行切割:
tput rmam
(用于重置模式自动保证金;tput smam
恢复)
您可以定义一个函数,例如:
nowrap() {
[ -t 1 ] && tput rmam
"$@"; local ret="$?"
[ -t 1 ] && tput smam
return "$ret"
}
alias nowrap='nowrap '
(alias
在 后强制别名扩展的部分nowrap
),称为:
nowrap ls -l ...
答案2
man ls
:
--color[=WHEN]
colorize the output; WHEN can be 'never', 'auto', or 'always' (the
default); more info below
您的ls
配置可能是--color=auto
,这意味着它仅在直接连接到终端时输出颜色。 (而不是像 cut 这样的另一个命令。)
您可以使用--color=always
,但请注意,整个颜色内容是通过插入打开和关闭颜色的特殊字符(转义序列)来工作的。如果您在彩色单词的中间进行剪切,您将删除“停止着色”序列,并且下一行也将被着色。
也许ls --color=always|less -RS
会做你想做的事。
答案3
要伪造到终端的输出,从而保留颜色格式,可以使用 (FreeBSD)命令(或诸如此类的工具)ls
在伪终端中运行script
ptymagic.c)。
script -q /dev/null ls -lG | tr -d '\r' | cut -c 1-$COLUMNS
ptymagic ls -lG | cut -c 1-$COLUMNS
答案4
less -RS
是我能想到的最接近的简单解决方案。可以要求著名的寻呼机less
处理变色转义序列 ( -R
) 并截断长行 ( -S
)。
它还具有诸如-E
在文件末尾退出以及-F
如果内容适合屏幕则立即退出等选项。
看看less
的开发人员是否愿意接受您想要的行为的功能请求,这将是很有趣的。它并不真正符合 的目的less
,但该实用程序已经基本上实现了所有必需的块,并且是最容易扩展以支持您的功能请求的实用程序。