Python正则表达到解析字符串和返回元组

时间:2011-06-07 05:02:48

标签: python regex string numbers return

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

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 个答案:

答案 0 :(得分:25)

我会使用单个正则表达式来匹配整行,并在命名组((?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"""...""")来使正则表达式更易于阅读。

答案 1 :(得分:3)

使用正则表达式:

#! /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)

答案 2 :(得分:3)

尝试使用拆分。

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

答案 3 :(得分:2)

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

import re

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

答案 4 :(得分:1)

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

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

你刚刚拆分了字符串,你现在有一个名字在第二个位置的列表,以及以下条目中的两个值,即

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

当然你也有“|”但是在你的数据集中似乎是一致的,所以处理它不是一个大问题。只是忽略它们。

答案 5 :(得分:0)

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

>>> 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的最早的应用之一。)