通过剪切保留颜色输出

通过剪切保留颜色输出

交互地使用 bash 我尝试使用 cut 来防止行长度超过我的终端宽度。但是,当使用带有彩色输出的命令时,所有颜色都会被剪切删除。例如: ls -lG | cut -c 1-$COLUMNS

有没有什么方法可以剪切并保留颜色格式?

答案1

你这里有两个问题

  1. ls -G当输出未到达终端(此处为管道)时,停止以颜色输出。 GNUls需要传递一个--color=always选项,对于 BSD ls,您需要将环境设置CLICOLOR_FORCE为非空值以告诉它始终以颜色输出。

  2. 颜色是通过输出转义序列来实现的,转义序列是字符序列,例如<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在伪终端中运行scriptptymagic.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,但该实用程序已经基本上实现了所有必需的块,并且是最容易扩展以支持您的功能请求的实用程序。

相关内容