首页 > 解决方案 > 按照惯例处理逗号和句号

问题描述

我有各种字符串实例,例如:

- hello world,i am 2000to -> hello world, i am 2000 to
- the state was 56,869,12th -> the state was 66,869, 12th
- covering.2% -> covering. 2%
- fiji,295,000 -> fiji, 295,000

为了处理第一种情况,我想出了两步正则表达式:

re.sub(r"(?<=[,])(?=[^\s])(?=[^0-9])", r" ", text) # hello world, i am 20,000to
re.sub(r"(?<=[0-9])(?=[.^[a-z])", r" ", text) # hello world, i am 20,000 to

但这以某些不同的方式破坏了文本,并且也没有涵盖其他情况。任何人都可以建议一个更通用的正则表达式来正确解决所有情况。我试过使用replace,但它做了一些意想不到的替换,这反过来又引发了一些其他问题。我不是正则表达式的专家,希望得到指点。

标签: pythonpython-3.xregex

解决方案


这种方法通过将文本分解为标记来涵盖上述情况:

in_list = [
        'hello world,i am 2000to',
        'the state was 56,869,12th',
        'covering.2%',
        'fiji,295,000',
        'and another example with a decimal 12.3not4,5 is right out',
        'parrot,, is100.00% dead'
        'Holy grail runs for this portion of 100 minutes,!, 91%. Fascinating'
    ]
tokenizer = re.compile(r'[a-zA-Z]+[\.,]?|(?:\d{1,3}(?:,\d{3})+|\d+)(?:\.\d+)?(?:%|st|nd|rd|th)?[\.,]?')
for s in in_list:
    print(' '.join(re.findall(pattern=tokenizer, string=s)))

#    hello world, i am 2000 to
#    the state was 56,869, 12th
#    covering. 2%
#    fiji, 295,000
#    and another example with a decimal 12.3 not 4, 5 is right out
#    parrot, is 100.00% dead
#    Holy grail runs for this portion of 100 minutes, 91%. Fascinating

分解正则表达式,每个标记都是最长的可用子字符串:

  • 只有带或不带句点或逗号的字母,[a-zA-Z]+[\.,]?
  • 或者|
  • 一个数字表达式,可能是
    • 1 到 3 位数字\d{1,3},后跟任意数量的逗号组 + 3 位数字(?:,\d{3})+
    • |任意数量的无逗号数字\d+
    • 可选的小数位后跟至少一位数字(?:\.\d+)
    • 可选的后缀(百分比、'st'、'nd'、'rd'、'th')(?:[\.,%]|st|nd|rd|th)?
    • 可选句号或逗号[\.]?

请注意,(?:blah)用于抑制re.findall' 的自然愿望,即告诉您每个带括号的组如何在个人基础上匹配。在这种情况下,我们只希望它在字符串中向前走,并?:完成此操作。


推荐阅读