我有一个如下字符串:
date Not Important value NotImportant2
11.11.13 useless . useless,21 useless 2 14.21 asmdakldm
21.12.12 fmpaosmfpoamsp 4 41 ajfa9si90
我必须在最后提取日期和值。
如果我使用标准程序匹配多个单词,则pyparsing将“Not Important”列的最后一个数字与“value”匹配。
anything = pp.Forward()
anything << anyword + (value | anything)
myParser = date + anything
我认为最好的方法是强迫pyparsing匹配至少2个空格,但我真的不知道如何。有什么建议吗?
答案 0 :(得分:2)
要匹配2个或更多空格,您可以使用\s{2,}
此表达式将:
^(\d{2}\.\d{2}\.\d{2})[^\r\n]*\s(\S+)\s{2,}\S+\s*(?:[\r\n]|\Z)
示例文字
date Not Important value NotImportant2
11.11.13 useless . useless,21 useless 2 14.21 asmdakldm
21.12.12 fmpaosmfpoamsp 4 41 ajfa9si90
<强>匹配强>
[0][0] = 11.11.13 useless . useless,21 useless 2 14.21 asmdakldm
[0][3] = 11.11.13
[0][4] = 14.21
[1][0] = 21.12.12 fmpaosmfpoamsp 4 41 ajfa9si90
[1][5] = 21.12.12
[1][6] = 41
答案 1 :(得分:0)
这个示例文本是柱状的,所以pyparsing在这里有些过分。 你可以写:
fieldslices = [slice(0,8), # dateslice
slice(58,58+8), # valueslice
]
for line in sample:
date,value = (line[x] for x in fieldslices)
print date,value.strip()
并获得:
date value
11.11.13 14.21
21.12.12 41
但是既然你特别想要一个pyparsing解决方案,那么对于那些如此笨拙的东西,你可以使用GoToColumn
类:
from pyparsing import *
dateExpr = Regex(r'(\d\d\.){2}\d\d').setName("date")
realNum = Regex(r'\d+\.\d*').setName("real").setParseAction(lambda t:float(t[0]))
intNum = Regex(r'\d+').setName("integer").setParseAction(lambda t:int(t[0]))
valueExpr = realNum | intNum
patt = dateExpr("date") + GoToColumn(59) + valueExpr("value")
GoToColumn
与SkipTo
类似,但它不是前进到表达式的下一个实例,而是前进到特定的列号(其中列号从1开始,而不是从0开始)就像在字符串切片中一样。)
现在,解析器应用于您的示例文本:
# Normally, input would be from some text file
# infile = open(sourcefile)
# but for this example, create iterator from the sample
# text instead
sample = """\
date Not Important value NotImportant2
11.11.13 useless . useless,21 useless 2 14.21 asmdakldm
21.12.12 fmpaosmfpoamsp 4 41 ajfa9si90
""".splitlines()
infile = iter(sample)
# skip header line
next(infile)
for line in infile:
result = patt.parseString(line)
print result.dump()
print
打印:
['11.11.13', 'useless . useless,21 useless 2 ', 14.210000000000001]
- date: 11.11.13
- value: 14.21
['21.12.12', 'fmpaosmfpoamsp 4 ', 41]
- date: 21.12.12
- value: 41
请注意,值已经从字符串转换为int或float类型;您可以为自己编写一个解析操作,将dd.mm.yy
日期转换为Python日期时间。还要注意如何定义关联的结果名称;这些允许您按名称访问各个字段,例如print result.date
。
我还注意到你假设要获得一个或多个元素的序列,你使用了这个构造:
anything = pp.Forward()
anything << anyword + (value | anything)
虽然这确实有效,但它会创建一个运行时成本高昂的递归表达式。 pyparsing提供迭代等价物,OneOrMore
:
anything = OneOrMore(anyword)
或者,如果您更喜欢较新的'*' - 运算符表单:
anything = anyword*(1,)
请扫描pyparsing API文档,这些文档包含在pyparsing的源代码分发中,或者在http://packages.python.org/pyparsing/上联机。
欢迎来到Pyparsing!