You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python正则表达式解析餐厅销售数据分组错误排查求助

正则表达式解析餐厅销售数据分组错误解决

问题详情

我用Python正则表达式提取PDF中的餐厅销售样本数据并转换为JSON格式,当前使用的正则表达式为:

^\s*(\d+)\s*(([A-Za-z]+\s*)+)?(\d+)\s+(.+?)\s+(\d+.\d+)\s+(\d+.\d+)\s+(\d+.\d+)\s+(\d+.\d+)\s+(\d+.\d+)\s+(\d+.\d+)\s+(\d+.\d+)\s+(\d+.\d+)\s+(\d+.\d+)$

当解析样本字符串:

1 NA BEVERAGE 1100 ICED TEA 14.00 3.00 42.00 3.50 0.00 42.00 0.00 0.52 47.09

时,得到错误的分组结果:

{'item_category': 'NA BEVERAGE ', 'item_number': 'BEVERAGE '}

正确结果应为:

{'item_category': 'NA BEVERAGE ', 'item_number':'1100'}

期望的完整正确JSON输出:

{
  "item_rank": "1",
  "item_category": "NA BEVERAGE ",
  "item_number": "1100",
  "item_name": "ICED TEA",
  "number_sold": "14.00",
  "price_sold": "3.00",
  "amount": "42.00",
  "tax": "3.50",
  "cost": "0.00",
  "profit": "42.00",
  "food_cost": "0.00",
  "precent_sales": "0.52",
  "cat_sales": "47.09"
}

可复现的原始代码:

import re
import json

page_text_str = "   1 NA BEVERAGE 1100 ICED TEA 14.00 3.00 42.00 3.50 0.00 42.00 0.00 0.52 47.09"

sale_line_re = re.compile('^\s*(\d+)\s*(([A-Za-z]+\s*)+)?(\d+)\s+(.+?)\s+(\d+.\d+)\s+(\d+.\d+)\s+(\d+.\d+)\s+(\d+.\d+)\s+(\d+.\d+)\s+(\d+.\d+)\s+(\d+.\d+)\s+(\d+.\d+)\s+(\d+.\d+)$')
grouped_data = []

for line in page_text_str.split('\n'):
    print(line)   
    match = sale_line_re.match(line)
    if match:
        groups = match.groups()
        item = {
            "item_rank": groups[0],
            "item_category": groups[1],
            "item_number": groups[2],
            "item_name": groups[3],
            "number_sold": groups[4],
            "price_sold": groups[5],
            "amount": groups[6],
            "tax": groups[7],
            "cost": groups[8],
            "profit": groups[9],
            "food_cost": groups[10],
            "precent_sales": groups[11],
            "cat_sales": groups[12]
        }
        grouped_data.append(item)


for sale in grouped_data:
    print(sale)

问题原因

  1. 分组索引错误:原正则中(([A-Za-z]+\s*)+)?是嵌套分组,内部的([A-Za-z]+\s*)会捕获分组内最后一次匹配的内容(也就是BEVERAGE ),而完整的分类文本是外部分组groups[1]。但代码里错误地将groups[2](内部分组)赋值给了item_number,正确的item_number应该是后续的groups[3]。
  2. 未转义小数点:原表达式中\d+.\d+的.是正则元字符,会匹配任意字符,应该转义为\d+\.\d+才能精准匹配小数格式。
  3. 分组顺序对应错误:后续的数值字段索引全部错位,导致所有数值字段都对应到了错误的分组。

修正方案

1. 修正正则表达式

转义小数点,确保匹配小数的准确性,正则表达式调整为:

^\s*(\d+)\s*(([A-Za-z]+\s*)+)?(\d+)\s+(.+?)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)$

2. 修正代码分组索引

调整item_number及后续字段的分组索引,对应正确的捕获组:

  • item_number对应groups[3]
  • item_name对应groups[4]
  • 后续数值字段依次对应groups[5]到groups[13]

修正后的完整代码

import re
import json

page_text_str = "   1 NA BEVERAGE 1100 ICED TEA 14.00 3.00 42.00 3.50 0.00 42.00 0.00 0.52 47.09"

# 转义小数点,确保小数匹配精准
sale_line_re = re.compile(r'^\s*(\d+)\s*(([A-Za-z]+\s*)+)?(\d+)\s+(.+?)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)$')
grouped_data = []

for line in page_text_str.split('\n'):
    print(line)   
    match = sale_line_re.match(line)
    if match:
        groups = match.groups()
        item = {
            "item_rank": groups[0],
            # 可选:去除分类文本末尾多余空格
            "item_category": groups[1].strip() if groups[1] else None,
            "item_number": groups[3],
            "item_name": groups[4],
            "number_sold": groups[5],
            "price_sold": groups[6],
            "amount": groups[7],
            "tax": groups[8],
            "cost": groups[9],
            "profit": groups[10],
            "food_cost": groups[11],
            "precent_sales": groups[12],
            "cat_sales": groups[13]
        }
        grouped_data.append(item)

# 格式化输出JSON
for sale in grouped_data:
    print(json.dumps(sale, indent=2))

运行修正后的代码,即可得到期望的正确输出。


内容的提问来源于stack exchange,提问作者Pythonic Crow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 06:45:27