用转义序列替换控制字符和空格

时间:2013-10-23 16:33:25

标签: linux perl bash shell awk

我想用十六进制转义码替换控制字符(ASCII 0-31)和空格(ASCII 32)。例如:

$ escape 'label=My Disc'
label=My\x20Disc
$ escape $'multi\nline\ttabbed string'
multi\x0Aline\x09tabbed\x20string
$ escape '\'
\\

对于上下文,我正在编写一个用于状态DVD驱动器的脚本。它的输出设计为由另一个程序解析。我的想法是将每条信息打印成一个单独的空格分隔的单词。例如:

$ ./discStatus --monitor
/dev/dvd: no-disc
/dev/dvd: disc blank writable size=0 capacity=2015385600
/dev/dvd: disc not-blank not-writable size=2015385600 capacity=2015385600

我想将光盘的标签添加到此输出中。为了适应解析方案,我需要转义空格和换行符。我也可以做所有其他控制角色。

如果可能的话,我更愿意坚持使用bash,sed,awk,tr等。但是,我想不出用这些工具做到这一点的非常优雅的方法。如果基本的shell结构和工具没有很好的解决方案,我愿意使用perl或python。

3 个答案:

答案 0 :(得分:2)

这是我提出的Perl单线程。它使用/e在替换中运行代码。

perl -pe 's/([\x00-\x20\\])/sprintf("\\x%02X", ord($1))/eg'

与我的问题中的示例略有偏差:它为反斜杠而不是\x5C发出\\

答案 1 :(得分:0)

我会使用更高级别的语言。有三种不同类型的替换(控制字符和空格的单字符到多字符,其他可打印字符的标识,以及反斜杠加倍的特殊情况),我认为awk太多了, sed等等,可以简单地处理。

这是我的Python方法

def translate(c):
    cp = ord(c)
    if cp in range(33):
        return '\\x%02x'%(cp,)
    elif c == '\\':
        return r'\\'
    else:
        return c

if __name__ == '__main__':
    import sys
    print ''.join( map(translate, sys.argv[1]) )

如果需要考虑速度,可以将translate函数替换为预先构建的字典,将每个字符映射到所需的字符串表示。

答案 2 :(得分:-1)

哇,它看起来像一个相当简单的sed脚本 {1}用于您要替换的每个角色。