【问题标题】:Removing control / special characters from log file从日志文件中删除控制/特殊字符
【发布时间】:2011-11-25 20:16:08
【问题描述】:

我有一个由 tclsh 捕获的日志文件,它捕获所有退格字符(ctrl-H,显示为“^H”)和颜色设置序列(例如。^[[32m ....^[[0m )。什么是删除它们的有效方法?

^[...m

这很简单,因为我可以执行“sed -i /^[.*m//g”来删除它们

^H

现在我有“sed -i s/.^H//”,它“应用”了一个退格,但我必须继续循环,直到没有更多的退格。

while [ logfile == `grep -l ^H logfile` ]; do sed -i s/.^H// logfile ; done;

"sed -i s/.^H//g" 不起作用,因为它会匹配连续的退格。对于我的日志文件,这个过程需要 11 分钟,大约 6k 行,这太长了。

有没有更好的方法来删除退格?

【问题讨论】:

    标签: bash sed tcl


    【解决方案1】:

    您总是可以编写一个简单的管道命令来实现退格剥离,如下所示:

    #include <stdio.h>
    #include <stdlib.h>
    
    #define BUFFERSIZE 10240
    
    int main(int argc, char* argv[])
    {
        int c ;
        int buf[BUFFERSIZE] ;
        int pos = 0 ;
        while((c = getchar()) != EOF)
        {
            switch (c)
            {
            case '\b':
            {
                if (pos > 0)
                    pos-- ;
                break ;
            }
            case '\n':
            {
                int i ;
                for (i = 0; i < pos; ++i)
                    putchar(buf[i]) ;
                putchar('\n') ;
                pos = 0 ;
                break ;
            }
            default:
            {
                buf[pos++] = c ;
                break ;
            }
            }
        }
        return 0 ;
    } 
    

    我只对代码进行了最低限度的测试,您可能需要根据我们的线路大小调整缓冲区大小。为了安全起见,断言 pos 是

    或者,您可以首先使用捕获日志文件的 Tcl 代码实现类似的东西;但不知道它是如何工作的,这有点难以说。

    【讨论】:

    • +1,尽管您应该将 BUFFERSIZE 设为整数。 (我通常使用 4096。)
    • 看起来应该可以,虽然我希望有一个快速的 linux 命令。
    【解决方案2】:

    你可以试试:

    sed -i s/[^^H]^H//g
    

    这可能会或可能不会一次性奏效,但至少应该比您现在似乎做的一次更快。

    【讨论】:

    • 感谢您的建议。这对于具有多个退格序列的行来说是一种改进,但如果我有一串 10 个退格,我仍然需要循环 10 次。
    • 出于某种原因,这似乎永远运行。不知道为什么 [^^H] 似乎效果不佳。
    【解决方案3】:

    您知道“sed”不只是进行替换吗?不过,sed 脚本的命令必须在单独的行上(或者至少在我在这台机器上安装的 sed 版本上是这样)。

    sed -i bak 's/^[[^^]]*m//g
    : again
    s/[^^H]^H//g
    t again' logfile
    

    : 设置一个标签(在本例中为again),如果执行了任何替换(从开始/最后一个分支开始),t 将分支到一个标签。用合适的s 将它们包裹起来,直到它不能再被替换为止。

    【讨论】:

      【解决方案4】:

      只是把它放在这里,我最终这样做了。这不是一个很好的解决方案,也不像杰克逊的答案那样灵活,但在我的特殊情况下可以满足我的需要。我基本上是使用内部循环来生成 sed 的匹配字符串。

      # "Applies" up to 10 consecutive backspaces
      for i in {10..1}; do
        match=""
        for j in `seq 1 $i`; do
          match=".${match}^H"
        done;
      
        # Can't put quotes around s//g or else backspaces are evaluated
        sed -i s/${match}//g ${file-to-process}
      done;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-04
        • 2016-10-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多