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

如何编写Python正则表达式,从列表字符串提取指定字段?

正则表达式提取字段不符合预期的修正方案

问题描述

输入字符串列表如下:

x = ['abc >123%', 'Abc5d 12.3%', 'Hz-xyz = 321k/mL', 'N+ 456', '789 mm/min/1.3', '<=55']

期望提取name(名称)、symbol(符号)、value(数值)、unit(单位)字段,输出如下字典:

out = {
        'x1':{
                'name':'abc', 
                'symbol': '>', 
                'value': '123', 
                'unit': '%'
             },
        'x2':{
                'name':'Abc5d', 
                'symbol': None, 
                'value': '12.3', 
                'unit': '%'
              },
        'x3':{
                'name':'Hz-xyz', 
                'symbol':'=', 
                'value': '321', 
                'unit': 'k/mL'
              },
         'x4':{
                 'name':'N+',
                 'symbol': None,
                 'value': '456',
                 'unit': None
               },
         'x5':{
                 'name': None,
                 'symbol': None,
                 'value': '789',
                 'unit': 'mm/min/1.3'
               },
          'x6':{
                 'name': None,
                 'symbol': '<=',
                 'value': '55',
                 'unit': None
                }
      }

原代码输出与预期不符:

import re

def extract_info(x):
   out = {}
   pattern = r'([A-Za-z0-9-]+)\s*([&gt;&lt;=]{0,2})\s*([0-9.]+)\s*([A-Za-z/%]+)?'

   for i, string in enumerate(x, start=1):
       match = re.match(pattern, string)
       name, symbol, value, unit = match.groups() if match else (None, None, None, None)
       out[f'x{i}'] = {'name': name, 'symbol': symbol, 'value': value, 'unit': unit}

   return out

原正则的问题分析

  • 字符范围不全:原正则中name的匹配范围[A-Za-z0-9-]+没有包含+,导致无法匹配N+这种带+的名称;unit的匹配范围[A-Za-z/%]+没有包含.和连续/,无法匹配mm/min/1.3、k/mL这类结构。
  • 符号匹配错误:原正则里的[&gt;&lt;=]是HTML转义字符,实际应该用[<>]=?|=来匹配>、<、<=、>=、=这类符号。
  • 结构顺序不灵活:原正则强制要求name在前,但输入中存在name缺失(比如<=55)、symbol缺失(比如Abc5d 12.3%)等场景,无法覆盖。
  • 空格处理问题:符号和数值之间可能有空格(比如= 321)也可能没有(比如>123),原正则的空格匹配逻辑不够灵活。

修正后的代码

我们需要设计一个更灵活的正则,允许各个字段可选,同时覆盖所有字符场景:

import re

def extract_info(x):
    out = {}
    # 正则分组说明:
    # 1. name:可选,匹配含字母、数字、+、-的字符串,后跟可选空格
    # 2. symbol:可选,匹配<=、>=、<、>、=,后跟可选空格
    # 3. value:必填,匹配数字和小数点
    # 4. unit:可选,匹配含字母、数字、/、%、.、-的字符串
    pattern = r'^(?:([A-Za-z0-9+-]+)\s*)?(?:([<>]=?|=)\s*)?([0-9.]+)(?:\s*([A-Za-z0-9/%.-]+))?$'
    
    for i, string in enumerate(x, start=1):
        match = re.match(pattern, string.strip())
        name, symbol, value, unit = match.groups() if match else (None, None, None, None)
        # 将空值转为None,符合预期输出格式
        out[f'x{i}'] = {
            'name': name,
            'symbol': symbol,
            'value': value,
            'unit': unit
        }
    return out

# 测试验证
x = ['abc >123%', 'Abc5d 12.3%', 'Hz-xyz = 321k/mL', 'N+ 456', '789 mm/min/1.3', '<=55']
print(extract_info(x))

正则规则解释

  • ^(?:([A-Za-z0-9+-]+)\s*)?:可选的name分组,匹配字母、数字、+、-组成的字符串,后跟任意空格(可选),非捕获组包裹后整体作为可选模块。
  • (?:([<>]=?|=)\s*)?:可选的symbol分组,匹配<=、>=、<、>、=,后跟任意空格(可选),非捕获组包裹后整体作为可选模块。
  • ([0-9.]+):必填的value分组,匹配数字和小数点组成的数值字符串。
  • (?:\s*([A-Za-z0-9/%.-]+))?$:可选的unit分组,匹配字母、数字、/、%、.、-组成的单位字符串,前跟任意空格(可选),非捕获组包裹后整体作为可选模块,确保匹配到字符串结尾。

运行这段代码后,输出将完全符合预期格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 15:37:38