Python 正则表达式解析字符串并返回元组
Posted
技术标签:
【中文标题】Python 正则表达式解析字符串并返回元组【英文标题】:Python Regex to Parse String and Return Tuple 【发布时间】:2011-09-09 18:52:51 【问题描述】:我得到了一些可以使用的字符串。每个代表一个数据集,由数据集的名称和相关的统计信息组成。它们都有以下形式:
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 可以是整数或小数。
【问题讨论】:
这类具有明确定义字段的字符串通常使用字符串拆分、切分等更快、更容易解析。例如[str.strip for ss in "|".split(s)]
将帮助您入门。
【参考方案1】:
我会使用单个正则表达式来匹配整行,以及我想要的命名组中的部分 ((?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"""..."""
) 使正则表达式更易于阅读。
【讨论】:
这很好用。我喜欢其他一些海报所说的关于分裂的说法,我可以看到它有很多用途。但我之前尝试过,只能将数字作为字符串返回。非常感谢您的意见。内容非常丰富!【参考方案2】:使用正则表达式:
#! /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]
拆分:将您的字符串转换为字符串列表
lambda 函数:删除空格和'
选择器:只取预期的部分
【讨论】:
【参考方案4】:不确定我是否正确理解了你,但试试这个:
import re
print re.findall(r'\b\w+\b', yourtext)
【讨论】:
【参考方案5】:我必须同意其他说在你的字符串上使用 split() 方法的海报。如果你给定的字符串是,
>> s = "| 'TOMATOES_PICKED' | 914 | 1397 |"
你刚刚拆分了字符串,瞧,你现在有一个列表,名称在第二个位置,两个值在以下条目中,即
>> s_new = s.split()
>> s_new
['|', "'TOMATOES_PICKED'", '|', '914', '|', '1397', '|']
当然你也有“|”字符,但这在您的数据集中似乎是一致的,因此处理起来不是一个大问题。忽略它们。
【讨论】:
【参考方案6】:使用 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 应用之一。)
【讨论】:
以上是关于Python 正则表达式解析字符串并返回元组的主要内容,如果未能解决你的问题,请参考以下文章