首页 > 解决方案 > 从字符串中去除前导和尾随 ansi/tput 代码

问题描述

此处的应用程序正在“清理”字符串以包含在日志文件中。为了论证起见,我们假设 1) 在运行时对字符串进行着色是正确的;2)我需要屏幕上的前导和尾随空格,但从日志中删除了多余的空格。

此处的特定应用程序是生成日志文件。不是所有的行都会被着色,也不是所有的行都会有前导/尾随空格。

鉴于此,我想

  1. 删除设置颜色和重置的所有代码。原因一会就明白了
  2. 删除前导和尾随空格

当您(在任何地方)搜索如何在 bash 中去除颜色代码时,您可以找到许多不同的方法来完成它。然而,到目前为止,我发现似乎没有人解决尾随重置问题。$(tput sgr0)。在我看到的示例中,这是无关紧要的,但是我对去除前导/尾随空格的额外要求使其复杂化/使其成为一项要求。

这是我演示该问题的示例脚本:

#!/bin/bash

# Create a string with color, leading spaces, trailing spaces, and a reset
REPLY="$(tput setaf 2)       This is green        $(tput sgr0)"
echo "Colored output:  $REPLY"
# Remove initial color code
REPLY="$(echo "$REPLY" | sed 's,\x1B\[[0-9;]*[a-zA-Z],,g')"
echo "De-colorized output:  $REPLY"
# Remove leading and trailing spaces if present
REPLY="$(printf "%s" "${REPLY#"${REPLY%%[![:space:]]*}"}" | sed -n -e 'l')"
echo "Leading spaces removed:  $REPLY"
REPLY="$(printf "%s" "${REPLY%"${REPLY##*[![:space:]]}"}" | sed -n -e 'l')"
echo "Trailing spaces removed:  $REPLY"

输出是(不知道如何在这里给文本着色,假设第一行是绿色,后面的行不是):

屏幕帽

我愿意看到我的方式的错误,但在尝试不同的东西大约三个小时后,我很确定我的 google-fu 让我失望了。

感谢您的任何帮助。

标签: bashloggingsedcolorsansi

解决方案


这对我有用:

$ REPLY="$(tput setaf 2)       This is green        $(tput sgr0)"
$ echo -n $REPLY | od -vAn -tcx1
 033   [   3   2   m                               T   h   i   s
  1b  5b  33  32  6d  20  20  20  20  20  20  20  54  68  69  73
       i   s       g   r   e   e   n                            
  20  69  73  20  67  72  65  65  6e  20  20  20  20  20  20  20
     033   [   m 017
  20  1b  5b  6d  0f
$ REPLY=$(echo $REPLY | sed -r 's,\x1B[\[\(][0-9;]*[a-zA-Z]\s*(.*)\x1B[\[\(].*,\1,g' | sed 's/\s*$//')
$ echo -n $REPLY | od -vAn -tcx1
   T   h   i   s       i   s       g   r   e   e   n
  54  68  69  73  20  69  73  20  67  72  65  65  6e

显然sed 不支持非贪婪正则表达式,这将消除第二个正则表达式。

编辑:这个应该适用于您的输入:

$ REPLY="$(tput setaf 2)       This is green        "$'\x1B'"(B$(tput sgr0)"
$ echo -n $REPLY | od -vAn -tcx1
 033   [   3   2   m                               T   h   i   s
  1b  5b  33  32  6d  20  20  20  20  20  20  20  54  68  69  73
       i   s       g   r   e   e   n                            
  20  69  73  20  67  72  65  65  6e  20  20  20  20  20  20  20
     033   (   B 033   [   m 017
  20  1b  28  42  1b  5b  6d  0f
$ REPLY=$(echo "$REPLY" | sed -r -e 's,\x1B[\[\(][0-9;]*[a-zA-Z]\s*([^\x1B]+)\s+\x1B.*,\1,g' -e 's,\s*$,,')
$ echo -n $REPLY | od -vAn -tcx1
   T   h   i   s       i   s       g   r   e   e   n
  54  68  69  73  20  69  73  20  67  72  65  65  6e

与 bash 替换相比,我发现 sed 不那么神秘(或者像正则表达式一样不那么神秘)。但这只是我:)


推荐阅读