1

我想将字符串中给定位置的字母大写。我对特殊字母有疑问 - 具体来说是波兰字母:例如“±”。理想情况下,该解决方案也适用于法语、西班牙语等(ç、è 等)

dobry="costąm"
print(dobry[4].decode('utf-8').upper())

我得到:

  File "/usr/lib/python2.7/encodings/utf_8.py", line 16, in decode
    return codecs.utf_8_decode(input, errors, True)

UnicodeDecodeError: 'utf8' codec can't decode byte 0xc4 in position 0: unexpected end of data

而为此:

print("ą".decode('utf-8').upper())

我根据需要获得Ą。

对位置 0-3 上的字母更感兴趣的是,它在以下情况下可以正常工作:

print(dobry[5].decode('utf-8').upper())

我遇到同样的问题

4

3 回答 3

3

该字符串实际上如下所示:

>>> list(dobry)
['c', 'o', 's', 't', '\xc4', '\x85', 'm']

所以,dobry[5] == '\x85'因为字母ą由两个字节表示。要解决这个问题,只需使用 Python 3 而不是 Python 2。

于 2019-02-24T10:54:15.300 回答
2

UTF-8 可能使用多个字节来编码一个字符,因此遍历一个字节串并操作单个字节并不总是有效。最好解码为 Python 2 的unicode类型。执行您的操作,然后重新编码为 UTF-8。

>>> dobry="costąm"
>>> udobry = unicode(dobry, 'utf-8')
>>> changed = udobry[:4] + udobry[4].upper() + udobry[5]
>>> new_dobry = changed.encode('utf-8')
>>> print new_dobry
costĄm

正如@tripleee 评论的那样,非ascii 字符可能不会映射到单个unicode 代码点:“±”可能是单个代码点U+0105 带有OGONEK 的拉丁小写字母A,或者它可以“a”后跟U+0328 COMBINING组成奥格尼克。

在组合字符串中,“a”字符可以大写,“a”后跟 COMBINING OGONEK 将产生“Ą”(尽管它在 Python REPL 或终端中可能看起来像两个单独的字符,具体取决于终端设置)。

请注意,您需要在索引时考虑额外的字符。

也可以使用 unicodedata 模块中的工具将组合字符串规范化为单个代码点(规范)版本:

>>> unicodedata.normalize('NFC', u'costa\u0328m') ==  u"costąm"
True

但这可能会导致问题,例如,如果您将更改的字符串返回到期望保留组合字符的系统。

于 2019-02-24T11:06:39.950 回答
1

那怎么办:

print(dobry.decode('utf-8')[5].upper())
于 2019-02-24T10:58:39.093 回答