我正在使用Python 3中的argparse库从命令行参数读取Unicode字符串。这些字符串通常包含“普通”Unicode字符(扩展拉丁语等),但有时 - 特别是当字符属于从右到左的脚本时 - 将字符串编码为Unicode代码点更容易,例如\ u0644 。但是argparse将这些指示符视为一系列字符,并不会将它们转换为它们指定的字符。例如,如果命令行参数是
... -a "abc\06d2d" ...
然后我在argparse变量中得到的是
"abc\06d2d"
而不是预期的
"abcےd"
('c'和'd'之间的字符是yeh baree)。当然,这两种结果都是合乎逻辑的,只是第二种结果是我想要的结果。
我试图在解释器中重现这一点,但在大多数情况下,Python3会自动将类似“abc \ 06d2d”的字符串转换为“abcےd”。当我使用argparse读取字符串时不是这样......
我想出了一个转换功能,见下文。但我觉得我错过了一些更简单的东西。有没有更简单的方法来进行此转换? (显然我可以使用str.startswith()或正则表达式来匹配整个事物,而不是逐字逐句,但下面的代码实际上只是一个例子。看起来我不应该创建自己的函数这样做,特别是因为在某些情况下它似乎是自动发生的。)
---------我的代码如下---------
def ParseString2Unicode(sInString):
"""Return a version of sInString in which any Unicode code points of the form
\uXXXX (X = hex digit)
have been converted into their corresponding Unicode characters.
Example:
"\u0064b\u0065"
becomes
"dbe"
"""
sOutString = ""
while sInString:
if len(sInString) >= 6 and \
sInString[0] == "\\" and \
sInString[1] == "u" and \
sInString[2] in "0123456789ABCDEF" and \
sInString[3] in "0123456789ABCDEF" and \
sInString[4] in "0123456789ABCDEF" and \
sInString[5] in "0123456789ABCDEF":
#If we get here, the first 6 characters of sInString represent
# a Unicode code point, like "\u0065"; convert it into a char:
sOutString += chr(int(sInString[2:6], 16))
sInString = sInString[6:]
else:
#Strip a single char:
sOutString += sInString[0]
sInString = sInString[1:]
return sOutString
答案 0 :(得分:2)
您可能需要查看的是raw_unicode_escape
编码。
>>> len(b'\\uffff')
6
>>> b'\\uffff'.decode('raw_unicode_escape')
'\uffff'
>>> len(b'\\uffff'.decode('raw_unicode_escape'))
1
所以,函数将是:
def ParseString2Unicode(sInString):
try:
decoded = sInString.encode('utf-8')
return decoded.decode('raw_unicode_escape')
except UnicodeError:
return sInString
然而,这也与其他unicode转义序列匹配,例如\Uxxxxxxxx
。如果您只想匹配\uxxxx
,请使用正则表达式,如下所示:
import re
escape_sequence_re = re.compile(r'\\u[0-9a-fA-F]{4}')
def _escape_sequence_to_char(match):
return chr(int(match[0][2:], 16))
def ParseString2Unicode(sInString):
return re.sub(escape_sequence_re, _escape_sequence_to_char, sInString)
答案 1 :(得分:1)
一种简洁,灵活的处理方式是使用正则表达式:
return re.sub(
r"\\u([0-9A-Fa-f]{4})",
lambda m: chr(int(m[1], 16)),
sInString
)