0

我有一个带有销售记录的 SQLite 表——在字段 13 中的运费价格——基本上有 3 种可能性:

价格:例如。£15.20 免费未指定

问题是并不总是只有这些词:例如。它可以说“运费为 15.20 英镑”或“免运费”——我需要将其标准化为上述可能性。我使用正则表达式:

def correct_shipping(db_data):
pattern=re.compile("\£(\d+.\d+)") #search for price
pattern_free=re.compile("free") #search for free shipping
pattern_not=re.compile("not specified") #search for shipping not specified 

for every_line in db_data:
    try:
        found=pattern.search(every_line[13].replace(',','')).group(1)
    except:
        try:
            found=pattern_free.search(every_line[13]).group()
        except:
            found=pattern_not.search(every_line[13]).group()

    if found:
        query="UPDATE MAINTABLE SET Shipping='"+found+"' WHERE Id="+str(every_line[0])
        db_cursor.execute(query)
db_connection.commit()

但是这段代码引发了异常
AttributeError: 'NoneType' object has no attribute 'group' ——第一次以“5.20”形式触发它,因为没有找到任何模式。
问题是如何正确搜索字符串(是否需要 try/except

4

2 回答 2

2

第一个问题是您的代码没有正确处理故障。如果您想使用None在不匹配时返回的函数,您要么必须检查None,要么处理AttributeError尝试调用group它的结果。

你可以在前两个下面再多一层try/ 。except但这变得非常难以阅读。像这样的函数会简单得多:

match = pattern.search(every_line[13].replace(',',''))
if match:
    return match.group(1)
match = pattern_not.search(every_line[13])
if match:
    return match.group()
match = pattern_not.search(every_line[13])
if match:
    return match.group()

这使用与您的代码相同的正则表达式,但没有尝试调用group每个匹配是否成功的问题,因此它工作得很好,很简单。


有一些方法可以进一步简化这一点。例如,您不需要使用正则表达式来搜索固定字符串,例如"free"; 你可以使用str.findor str.index。或者,或者,您可以使用带有三向交替的单个正则表达式的搜索,而不是执行三个单独的搜索。


下一个问题是您的第一个模式是错误的。除了正则表达式特殊字符(或 Python 特殊字符......但您应该使用原始字符串,因此您不需要转义它们)之外,您不应该使用反斜杠转义任何内容,并且井号不是其中之一。

更重要的是,如果这是 Python 2.x,你永远不应该将非 ASCII 字符放入字符串文字中;只将它们放在 Unicode 文字中。(并且仅当您为源文件指定编码时。)

Python 的正则表达式引擎可以处理 Unicode……但如果你给它 mojibake 就不行,比如解码为 Latin-1 或其他东西的 UTF-8 磅符号。(事实上​​,即使你得到了所有的编码,最好给它 Unicode 模式和搜索字符串而不是编码的。否则,它无法知道它正在搜索 Unicode,或者某些字符不仅仅是一个字节长等)

于 2013-08-13T19:29:49.347 回答
0

不要搜索井号。搜索数字,然后自己手动添加井号。

import re

strings = [
    "5.20",
    "$5.20",
    "$.50",
    "$5",
    "Shipping is free",
    "Shipping: not specified",
    "free",
    "not specified",
]

pattern = r"""
    \d*                     #A digit 0 or more times 
    [.]?                    #A dot, optional
    \d+                     #A digit, one or more times 
    | free                  #Or the word free
    | not \s+ specified     #Or the phrase "not specified"
"""

regex = re.compile(pattern, flags=re.X)
results = []

for string in strings:
    md = re.search(regex, string)

    if md:
        match = md.group()
        if re.search(r"\d", match):
            match = "$" + match
        results.append(match)
    else:
        print "Error--no match!"

print results

--output:--
['$5.20', '$5.20', '$.50', '$5', 'free', 'not specified', 'free', 'not specified']
于 2013-08-13T19:21:20.163 回答