【问题标题】:Python - regex - special characters and ñPython - 正则表达式 - 特殊字符和ñ
【发布时间】:2015-12-28 15:24:45
【问题描述】:

我有这个脚本来测试正则表达式以及 unicode 的行为方式:

# -*- coding: utf-8 -*-
import re

p = "Solo voy si se sucedierón o se suceden mañana los siguienñes eventos:"

w = re.findall('[a-zA-ZÑñ]+',p.decode('utf-8'), re.UNICODE)

print(w)

print 声明显示了这一点:

[u'Solo', u'voy', u'si', u'se', u'sucedier', u'n', u'o', u'se', u'suceden', u'ma', u'ana', u'los', u'siguien', u'es', u'eventos']

"sucedierón" 被转换为"u'sucedier', u'n'",同样"mañana" 变成"u'ma', u'ana'"。

我尝试过解码,将'\xc3\xb1a' 添加到'Ñ' 的正则表达式中

后来在阅读了一些文档后,我意识到使用 [a-zA-Z] 只匹配 ASCII 字符。这就是为什么我必须更改为 r'\b\w+\b' 以便我可以在正则表达式中添加标志

w = re.findall(r'\b\w+\b', p, re.UNICODE) 

但这没有用。

我也试过先decode(),然后再findall():

p = "Solo voy si se sucedierón o se suceden mañana los siguienñes eventos:"
U = p.decode('utf8')

如果我打印变量U

"Solo voy si se sucedierón o se suceden mañana los siguienñes eventos:"

我看到输出符合预期,但是当我再次使用findall() 时:

[u'Solo', u'voy', u'si', u'se', u'sucedier\xf3n', u'o', u'se', u'suceden', u'ma\xf1ana', u'los', u'siguien\xf1es', u'eventos']

现在单词已完成,但 ó 被替换为 \xf3n,ñ 被替换为 \xf1,unicode 值。

我怎样才能findall() 获取非ASCII 字符"ñ","á", "é", "í", "ó", "ú"

我现在在 SO 中有很多这样的问题,相信我我读了很多,但我就是找不到缺失的部分。

编辑

我正在使用 python 2.7

编辑 2 其他人可以尝试@LetzerWille 的建议吗?不适合我

【问题讨论】:

    标签: python regex unicode


    【解决方案1】:

    它对我有用。我使用 Pycharm 并将控制台设置为 utf-8。

    您需要将输出控制台配置为 utf-8 ....

    p = "Solo voy si se sucedierón o se suceden mañana los siguienñes eventos:"
    
    w = re.findall('ñ',p, re.UNICODE)
    
    print(w)
    
    ['ñ', 'ñ']
    
    w = re.findall('[a-zA-ZÑñó:]+',p, re.UNICODE)
    
    print(w)
    
    ['Solo', 'voy', 'si', 'se', 'sucedierón', 'o', 'se', 'suceden', 'mañana', 'los', 'siguienñes', 'eventos:']
    

    【讨论】:

    • 对不起,如何将控制台设置为 utf-8?
    • @NachoMiguel 这取决于您的环境。每个编辑器都使用自己的系统变量。对于 PYcharm,它是 vmoptions 文件中的 -Dconsole.encoding=UTF-8 作为最后一行。
    • 你知道如果我在网站上使用它,字母ñ和重音会正确显示吗?
    • 只是这样做了。它没有用。感谢您的建议
    • @NachoMiguel。我看到您使用 p.decode ...它在 Python 3 中使用。在 Python 2.x 中,您应该使用 unicode(p)。还运行 sys.getdefaultencoding() 以查看系统的默认配置。它可能不是 utf-8
    【解决方案2】:

    你的代码应该写成:

    w = re.findall(u'[a-zA-ZÑñ]+', p.decode('utf-8'))
    

    请自行将其他字符添加到字符类中,因为我不知道您要匹配的完整字符集。

    在处理 Unicode 文本时,请确保输入字符串和模式均为 unicode1 类型。

    1unicode 在逻辑上是 UTF-16 代码单元(在窄构建中)或 UTF-32 代码单元/代码点(在宽构建中)的数组。如果您打算使用 Python 处理 Unicode 文本,为了避免窄版本中星体平面字符的问题,我建议使用 Python 3.3 及更高版本,或者始终使用其他版本的宽版本。

    在 Python 2 中,str is simply an array of bytes,因此模式中 ASCII 范围之外的字符将简单地解释为在源编码中构成该字符的字节序列:

    >>> [i for i in '[a-zA-ZÑñ]+']
    ['[', 'a', '-', 'z', 'A', '-', 'Z', '\xc3', '\x91', '\xc3', '\xb1', ']', '+']  
    

    在编译str 和unicode 对象时比较re.DEBUG 的输出:

    >>> re.compile('[a-zA-ZÑñ]+', re.DEBUG)
    max_repeat 1 4294967295
      in
        range (97, 122)
        range (65, 90)
        literal 195      # \xc3
        literal 145      # \x91
        literal 195
        literal 177
    <_sre.SRE_Pattern object at 0x6fffffd0dd8>
    
    >>> re.compile(u'[a-zA-ZÑñ]+', re.DEBUG)
    max_repeat 1 4294967295
      in
        range (97, 122)
        range (65, 90)
        literal 209      # Ñ
        literal 241      # ñ
    <_sre.SRE_Pattern object at 0x6ffffded030>
    

    由于您没有使用\s、\w、\d、re.UNICODE 标志无效,可以将其删除。

    【讨论】:

      【解决方案3】:

      Python 中带有重音符号(变音符号)的正则表达式

      re.UNICODE flag 允许您将单词字符 \w 和单词边界 \b 与变音符号(重音符号和波浪线)一起使用。这对于匹配不同语言的单词非常有用。

      1. 将文本从 UTF-8 解码为
      2. 确保将模式和主题文本作为 传递给正则表达式函数。
      3. 结果是一个字节数组,可以循环/映射以再次编码回 UTF-8
      4. 打印数组会显示转义的非 ASCII 字节,但单独打印每个字符串是安全的。

      代码:

      # -*- coding: utf-8 -*-
      # http://stackoverflow.com/q/32872917/5290909
      #python 2.7.9
      
      import re
      
      text = "Solo voy si se sucedierón o se suceden mañana los siguienñes eventos:"
      # Decode to unicode
      unicode_text = text.decode('utf8')
      
      matches = re.findall(ur'\b\w+\b', unicode_text, re.UNICODE)
      
      # Encode back again to UTF-8
      utf8_matches = [ match.encode('utf-8') for match in matches ]
      
      # Print every word
      for utf8_word in utf8_matches:
          print utf8_word
      

      ideone Demo

      【讨论】:

      • 啊,我错过了 OP 的第二个解决方案。您可能想提一下,OP 使用r'\b\w+\b' 的解决方案已经是正确的。
      猜你喜欢
      • 1970-01-01
      • 2010-10-13
      • 1970-01-01
      • 1970-01-01
      • 2018-06-13
      • 2023-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多