我正在使用 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
您可能想要查看的是raw_unicode_escape编码。
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,请使用正则表达式,如下所示:
\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)