regex 在Python中使用正则表达式从输入字符串列表中提取信息

fzsnzjdm  于 2023-08-08  发布在  Python
关注(0)|答案(4)|浏览(129)

我有下面的输入列表,我想提取名称,符号,值和单位,并作为字典输出。
例如,输入:

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

字符串
预期的输出:

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
                }
      }


我使用下面的代码行,但输出与预期的输出不一样。

def extract_info(x):
   out = {}
   pattern = r'([A-Za-z0-9-]+)\s*([><=]{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


有人能建议如何正确地编写正则表达式,以从Python中的输入列表中获得预期的输出吗?

  • 谢谢-谢谢
ubbxdtey

ubbxdtey1#

import re
from pprint import pprint

def extract_info(x):
    out = {}
    pattern = r'([A-Za-z0-9-+]*)\s*([><=]*)\s*([0-9.]*)\s*(.*)'

    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)        
        name = name if name else None
        symbol = symbol if symbol else None
        out[f'x{i}'] = {'name': name, 'symbol': symbol, 'value': value, 'unit': unit}
    return out

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

字符串
输出量:

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

ylamdve6

ylamdve62#

import re

def extract_info(x):
  out = {}
  pattern =r'([a-zA-z]+[^><= ]*){0,1}\s*([><=]*){0,1}\s*([0-9\.]+)\s*(.*){0,1}\s*'
  for i, string in enumerate(x, start=1):
    match = re.match(pattern, string)
    groups = match.groups() if match else (None, None, None, None)
    # print(groups)
    name, symbol, value, unit = [group if group and group.strip() != '' else None for group in groups]

    out[f'x{i}'] = {'name': name, 'symbol': symbol, 'value': value, 'unit': unit}

  return out

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

print(extract_info(x))

字符串
产出

{
'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}
}

flseospp

flseospp3#

在这四个部分中:名称、符号、值和单位;只有该值是强制性的,其他部分是可选的。另外,空白空间可以在部件之间。这意味着正则表达式可以很复杂。处理复杂正则表达式的最好方法是使用re.VERBOSE标志来编译它。此标志允许表达式中有额外白色和注解,使其更易于理解。

import re
import pprint

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

pattern = re.compile(
    r"""
# Optional spaces
\s*

# Name: optional, starts with a letter and does not contain symbols or spaces
(?P<name>[a-zA-z]+[^><= ]*){0,1}

\s*

# Symbol: optional, any relational symbol
(?P<symbol>[><=]*){0,1}

\s*

# Value: decimal, including the dot
(?P<value>[0-9\.]+)

\s*

# Unit: optional, anything after the value
(?P<unit>.*){0,1}
\s*
""",
    re.VERBOSE,
)
out = {}
for i, text in enumerate(x, 1):
    key = f"x{i}"
    matched = pattern.match(text)
    if matched:
        value = {k: v or None for k, v in matched.groupdict().items()}
        out[key] = value
    else:
        out[key] = None

pprint.pprint(out)

字符串
输出如下:

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

备注

  • (?P<symbol>...)表达式为该段提供了一个名称:“symbol”。此名称是groupdict()返回的字典中的键
  • {0,1}表示此段可能发生0次或1次。换句话说,它最多发生1次。
  • 因为我们使用re.VERBOSE标志来编译正则表达式,所以我们可以自由地向表达式中添加空行和白色。他们被忽视了。
  • {k: v or None for k, v in matched.groupdict().items()}代码段将任何空字符串“”转换为None
kh212irz

kh212irz4#

这将把所有字段推到正确的匹配位置。

import re
re.findall(r"'([^\s']*?)\s*([<>=]*)\s*((?:\d+(?:\.\d*)?|\.\d+)?)\s*([^\s']*)'", r"x = ['abc >123%', 'Abc5d 12.3%', 'Hz-xyz = 321k/mL', 'N+ 456', '789 mm/min/1.3', '<=55']")

字符串
产出

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


正则表达式布局

'
# name
( [^\s']*? )                  # (1)
\s* 
# symbol
( [<>=]* )                    # (2)
\s* 
# value
(                             # (3 start)
   (?:
      \d+ 
      (?: \. \d* )?
    | \. \d+ 
   )?
)                             # (3 end)
# unit
\s* 
( [^\s']* )                   # (4)
'

相关问题