将<u9999>格式的unicode字符转换为ASCII等效字符的脚本</u9999>

时间:2011-04-03 02:07:22

标签: python xml bash unicode

我在Linux语言环境文件/usr/share/i18n/locales(如pt_BR)中做了一些更改,以更改日期,时间,数字等的默认格式。但是因为unicode字符在<U9999>中显示为字符串格式,文字很难阅读。

以下是它的片段:

LC_TIME
abday   "<U0044><U006F><U006D>";"<U0053><U0065><U0067>";/
    "<U0054><U0065><U0072>";"<U0051><U0075><U0061>";/
    "<U0051><U0075><U0069>";"<U0053><U0065><U0078>";/
    "<U0053><U00E1><U0062>"

那么,如何制作一个简单的脚本(可能是bash,python,pearl,等等)来转换此文本,将<Uxxxx>代码替换为它们的ASCII等价物? (是的,它们都是低于255的ASCI字符,大多数甚至低于127)

如果收到多个答案,我接受最优雅和/或更详细解释的答案(如命令中使用的选项和标志)

例如,上述文本将转换为:

LC_TIME
abday   "Dom";"Seg";/
    "Ter";"Qua";/
    "Qui";"Sex";/
    "Sáb"

另一个可能相反的脚本的奖励积分:将给定字符串的所有字符转换为<Uxxx>格式。

谢谢!

2 个答案:

答案 0 :(得分:2)

使用字段

#!/bin/bash

awk -F'<U0+|>' '{
    for(i=1;i<=NF;i++)
        if($i ~ "^[0-9A-F]+$")
            $i=sprintf("%c", strtonum("0x"$i))
}1' OFS="" /path/to/infile

解释

  1. -F'<U0+|>':这就是使这个脚本如此简短的神奇之处。我们告诉awk字段分隔符是<U0+或简单>。这样做的好处是,awk会自动为我们剥离这些字符,因此在进行strtonum()转换时,我们无需使用gsub()手动执行此操作。

  2. for(i=1;i<=NF;i++):遍历每个字段

  3. if($i ~ "^[0-9A-F]+$"):检查当前字段是否仅由十六进制数字组成。请记住,由于#1之上的#1 <U006F>此时将被视为6F
  4. $i=sprintf("%c", strtonum("0x"$i)):将十六进制数字替换为其对应的ascii值。我们必须在字段$i前添加"0x"前缀,以便awk知道它的十六进制值
  5. }1:强制性print的快捷方式始终打印每一行
  6. OFS="":将输出字段分隔符设置为空字符串。如果我们不这样做,我们会在输出<U0+>
  7. 的地方输出空格

    使用match()[需要gawk]

    #!/bin/bash
    
    gawk '{
        while(match($0, /<U[0-9A-F]+>/)){
            pat = substr($0,RSTART,RLENGTH)
            gsub(/U0+|[<>]/,"",pat)
            asc = sprintf("%c", strtonum("0x"pat))
            $0 = substr($0, 1, RSTART-1) asc substr($0, RSTART+RLENGTH)
        }
    }1' /path/to/infile
    

答案 1 :(得分:1)

这是Python中的一个脚本,使用unidecode module<U9999>字符串转换为ASCII(0-127)等效字符:

#!/usr/bin/env python
import fileinput, re, sys
from unidecode import unidecode # to install, run: $ pip install unidecode

for line in fileinput.input(inplace='--inplace' in sys.argv):
    print re.sub(r'<U([0-9A-F]{4})>',
                 lambda m: unidecode(unichr(int(m.group(1), 16))),
                 line),

它接受来自stdin和/或命令行给出的文件的输入。

$ u9999-to-ascii data.in
LC_TIME
abday   "Dom";"Seg";/
    "Ter";"Qua";/
    "Qui";"Sex";/
    "Sab"

请注意,由于ascii不支持,因此没有á字符,因此脚本将其替换为ascii analog a

如果你不需要ascii那么:

#!/usr/bin/env python
from __future__ import print_function
import fileinput, re, sys

for line in fileinput.input(mode='rb', inplace='--inplace' in sys.argv):
    print(re.sub(br'<U([0-9A-F]{4})>', lambda m: br'\u'+m.group(1),
                 line).decode('raw-unicode-escape'), end='')

此脚本适用于Python2.6 +和Python3.x.例如:

$ u9999-to-unicode.py data.in
LC_TIME
abday   "Dom";"Seg";/
    "Ter";"Qua";/
    "Qui";"Sex";/
    "Sáb"

注意,有á。如果终端编码不支持data.in中的所有Unicode字符,则此脚本可能会产生错误。在这种情况下,您可以使用.encode()方法。