Python 正则表达式解析字符串并返回元组

问题描述 投票:0回答:6

我得到了一些可以使用的字符串。每个代表一个数据集,由数据集的名称和相关统计数据组成。它们都有以下形式:

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 可以是整数,也可以是小数。

我对编程非常陌生,所以如果这个问题看起来很初级,我深表歉意,但我一直在非常努力地阅读和搜索与我的情况接近的答案,但没有运气。

python regex string numbers return
6个回答
34
投票

我会使用单个正则表达式来匹配整行,并将我想要的部分放在命名组中(

(?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)

要将

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

我使用了

re.VERBOSE
标志和原始多行字符串 (
r"""..."""
) 来使正则表达式更易于阅读。


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)

3
投票

尝试使用拆分。

s= "| 'TOMATOES_PICKED'                                  |       914 |       1397 |"
print map(lambda x:x.strip("' "),s.split('|'))[1:-1]
  • Split:将字符串转换为字符串列表
  • lambda 函数:删除空格和
    '
  • 选择器:只取预期的部分

2
投票

不确定我是否正确理解了你,但试试这个:

import re

print re.findall(r'\b\w+\b', yourtext)

1
投票

我必须同意其他海报,他们说在字符串上使用 split() 方法。如果您给定的字符串是,

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

您只需拆分字符串,瞧,现在您有了一个列表,其中第二个位置是名称,以及以下条目中的两个值,即

>> s_new = s.split()
>> s_new
['|', "'TOMATOES_PICKED'", '|', '914', '|', '1397', '|']

当然你也有“|”字符,但这似乎在您的数据集中是一致的,因此这不是一个需要处理的大问题。忽略他们即可。


0
投票

通过 pyparsing,您可以让解析器为您创建一个类似字典的结构,使用第一列值作为键,使用后续值作为该键的值数组:

>>> from pyparsing import *
>>> s = "| 'TOMATOES_PICKED'                                  |       914 |       1397 |"
>>> VERT = Suppress('|')
>>> title = quotedString.setParseAction(removeQuotes)
>>> integer = Word(nums).setParseAction(lambda tokens:int(tokens[0]))
>>> entry = Group(VERT + title + VERT + integer + VERT + integer + VERT)
>>> entries = Dict(OneOrMore(entry))
>>> data = entries.parseString(s)
>>> data.keys()
['TOMATOES_PICKED']
>>> data['TOMATOES_PICKED']
([914, 1397], {})
>>> data['TOMATOES_PICKED'].asList()
[914, 1397]
>>> data['TOMATOES_PICKED'][0]
914
>>> data['TOMATOES_PICKED'][1]
1397

这已经理解了多个条目,因此您只需向其传递一个包含所有数据值的多行字符串,并且将为您构建一个单键数据结构。 (处理这种用管道分隔的表格数据是我最早的 pyparsing 应用程序之一。)

© www.soinside.com 2019 - 2024. All rights reserved.