Unix - 如何通过管道转换八进制转义序列

时间:2017-04-17 23:05:33

标签: bash unix utf-8 octal

我从文件中提取数据(在这种情况下是一个exim邮件日志),并且通常会将字符保存在转义的八进制序列中,例如\ NNN,其中' N' N' N'表示八进制值0-7。这主要发生在主题以非拉丁字符(例如阿拉伯语)编写时。

我的目标是找到最简单的方法来转换这些八进制字符,以便在我的utf-8启用的终端中正确显示,特别是在&less;' less'因为有很多输出的可能性。

到目前为止,我发现的最佳方法如下:

arbitrary_stream | { while read -r temp; do printf %b "$temp\n"; done } | less

这似乎工作得很好,但是我会假设有一些翻译工具,或者甚至可能是一个内置于“少”的翻译工具。处理这个。我还发现,如果你使用像sed之类的东西在每个\之后注入0,你可以将它存储为变量,然后使用' echo -e $ data'然而,这比之前的解决方案更加混乱。

测试用例:

octalvar="\342\202\254"

预期产量减少:

我正在寻找更清洁,更完整或更好的东西,而不仅仅是上述解决方案:

echo $octalvar | do_something | less

echo $octalvar | less --some_magic_flag

有什么建议吗?或者我的解决方案是否像我期望的一样干净?

2 个答案:

答案 0 :(得分:0)

这是我目前的版本:

echo $arbitrary | { IFS=$'\n'; while read -r temp; do printf %b "$temp\n"; done; unset IFS; } | iconv -f utf-8 -t utf-8 -c | less

答案 1 :(得分:0)

GNU awk中的转换(使用strtonum)。它被证明是一个麻烦所以代码是一团糟,也许可以简化,随意建议:

awk '{
    while(match($0,/\\[0-8]{3}/)) {  # search for \NNNs
        o=substr($0,RSTART,RLENGTH)  # extract it
        sub(/\\/,"0",o)              # replace \ with 0 for strtonum
        c=sprintf("%c",strtonum(o))  # convert to a character
        sub(/\\[0-8]{3}/,c)          # replace the \NNN with the char
    }
}1' foo > bar

或将单引号之间的代码粘贴到文件above_program.awk,然后像awk -f above_program.awk foo > bar一样运行。测试文件foo

test 123 \342\202\254

在非UTF8语言环境中运行它,我使用语言环境C:

$ locale 
...
LC_ALL=C
$ awk -f above_program.awk foo
test 123 €

如果您运行UTF8语言环境,则会发生转换:

$ locale
...
LC_ALL=en_US.utf8
$ awk -f above_program.awk foo
test 123 â¬