接受一切,直到"超过1个空格",使用pyparsing

时间:2012-10-19 14:17:38

标签: python python-2.7 pyparsing

我有一个文件,部分内容如下:

string                     0            1           10
string with white space    0            10          30
string9 with number 9      10           20          50
string_ with underline     10           50          1
(string with parentese)    50           20          100

我需要解析每一行,如:

[[string, 0 ,1 ,10], ....]

正如你在上面看到的那样,第一部分几乎可以是任何东西,我能想到解析这个的唯一方法是接受任何东西,直到我有2个空白字符,然后它只是数字。

但我在 pyparsing doc中找不到这个“UNTIL”功能。

2 个答案:

答案 0 :(得分:2)

以下代码示例实现了您的目标(与@PaulMcGuire建议的先前版本相比有所改进):

from __future__ import print_function

from pyparsing import CharsNotIn, Group, LineEnd, OneOrMore, Word, ZeroOrMore
from pyparsing import delimitedList, nums 

SPACE_CHARS = ' \t'
word = CharsNotIn(SPACE_CHARS)
space = Word(SPACE_CHARS, exact=1)
label = delimitedList(word, delim=space, combine=True)
# an alternative contruction for 'label' could be:
# label = Combine(word + ZeroOrMore(space + word))
value = Word(nums)
line = label('label') + Group(OneOrMore(value))('values') + LineEnd().suppress()

text = """
string                     0            1           10
string with white space    0            10          30
string9 with number 9      10           20          50
string_ with underline     10           50          1
(string with parentese)    50           20          100
""".strip()

print('input text:\n', text, '\nparsed text:\n', sep='\n')
for line_tokens, start_location, end_location in line.scanString(text):
    print(line_tokens.dump())

给出以下输出:

input text:

string                     0            1           10
string with white space    0            10          30
string9 with number 9      10           20          50
string_ with underline     10           50          1
(string with parentese)    50           20          100

parsed text:

['string', ['0', '1', '10']]
- label: string
- values: ['0', '1', '10']
['string with white space', ['0', '10', '30']]
- label: string with white space
- values: ['0', '10', '30']
['string9 with number 9', ['10', '20', '50']]
- label: string9 with number 9
- values: ['10', '20', '50']
['string_ with underline', ['10', '50', '1']]
- label: string_ with underline
- values: ['10', '50', '1']
['(string with parentese)', ['50', '20', '100']]
- label: (string with parentese)
- values: ['50', '20', '100']

解析后的值可以作为字典获得,第一列(在上面的示例中名为label)作为键,其余列的列表(上面名为values)为具有以下dict理解的值:

{label: values.asList() for label, values in line.searchString(text)}

其中linetext是上述示例中的变量,生成以下结果:

{'(string with parentese)': ['50', '20', '100'],
 'string': ['0', '1', '10'],
 'string with white space': ['0', '10', '30'],
 'string9 with number 9': ['10', '20', '50'],
 'string_ with underline': ['10', '50', '1']}

答案 1 :(得分:2)

为了完整起见,这个不使用pyparsing

import re
lines   = re.compile("\r?\n").split(text)
pattern = re.compile("\s\s+")
for line in lines:
  print pattern.split(line)
#['string', '0', '1', '10']
#['string with white space', '0', '10', '30']
#['string9 with number 9', '10', '20', '50']
#['string_ with underline', '10', '50', '1']
#['(string with parentese)', '50', '20', '100']