用Python正则解析字符串并返回元组

21 投票
6 回答
67438 浏览
提问于 2025-04-16 19:05

我现在有一些字符串需要处理。每个字符串代表一个数据集,里面包含了数据集的名称和相关的统计数据。它们的格式都是这样的:

s = "| 'TOMATOES_PICKED'       |   914 |   1397 |"

我想写一个函数,能够解析这个字符串,并返回数据集的名称、第一个数字和第二个数字。这些字符串有很多,每个都有不同的名称和相关的统计数据,所以我觉得用正则表达式来处理是最好的方法。以下是我目前的进展:

def extract_data2(s):
    import re
    name = re.search("'(.*?)'", s).group(1)
    n1 = re.search('\|(.*)\|', s)
    return name, n1

我查了一些关于正则表达式的资料,已经找到了如何提取名称的方法。对于我处理的每个字符串,数据集的名称是被单引号包围的,所以我就是通过这个找到名称的。这个部分运行得很好。我的问题在于如何提取数字。

我现在的想法是尝试匹配一个在竖线(|)后面,接着是任意字符(这就是我用.*的原因),然后再跟一个竖线的模式,以此来获取第一个数字。有没有人知道我该如何在Python中做到这一点?

我在上面的代码中尝试提取第一个数字时,返回的基本上是整个字符串,而我只想要那个数字。

我的想法是,这个函数能够:

return name, n1, n2

这样当用户输入一个字符串时,它就能解析这个字符串并返回重要的信息。我注意到在我尝试提取数字的过程中,返回的数字是以字符串的形式出现的。有没有办法让n1或n2直接作为数字返回?请注意,对于某些字符串,n1和n2可能是整数,也可能是带小数的。

我刚开始学习编程,所以如果这个问题看起来很基础,我很抱歉,但我一直在努力寻找与我情况相近的答案,却没有找到。

6 个回答

3

试试用分割功能。

s= "| 'TOMATOES_PICKED'                                  |       914 |       1397 |"
print map(lambda x:x.strip("' "),s.split('|'))[1:-1]
  • 分割:把你的字符串变成一个字符串列表
  • lambda函数:去掉空格和'符号
  • 选择器:只保留你需要的部分
7

使用正则表达式:

#! /usr/bin/env python

import re

tests = [
"| 'TOMATOES_PICKED'                                  |       914 |       1397 |",
"| 'TOMATOES_FLICKED'                                 |     32914 |       1123 |",
"| 'TOMATOES_RIGGED'                                  |        14 |       1343 |",
"| 'TOMATOES_PICKELED'                                |         4 |         23 |"]

def parse (s):
    mo = re.match ("\\|\s*'([^']*)'\s*\\|\s*(\d*)\s*\\|\s*(\d*)\s*\\|", s)
    if mo: return mo.groups ()

for test in tests: print parse (test)
35

我会用一个正则表达式来匹配整行内容,并把我想要的部分放在命名组里((?P<name>exampl*e))。

import re
def extract_data2(s):
    pattern = re.compile(r"""\|\s*                 # opening bar and whitespace
                             '(?P<name>.*?)'       # quoted name
                             \s*\|\s*(?P<n1>.*?)   # whitespace, next bar, n1
                             \s*\|\s*(?P<n2>.*?)   # whitespace, next bar, n2
                             \s*\|""", re.VERBOSE)
    match = pattern.match(s)
    
    name = match.group("name")
    n1 = float(match.group("n1"))
    n2 = float(match.group("n2"))
    
    return (name, n1, n2)

为了把 n1n2 从字符串转换成数字,我使用了 float 函数。(如果它们只是整数,我会用 int 函数。)

我使用了 re.VERBOSE 标志和原始多行字符串(r"""..."""),这样可以让正则表达式更容易阅读。

撰写回答