Python 用pyparsing解析冒号分隔的字符串的最佳方法是什么

Python 用pyparsing解析冒号分隔的字符串的最佳方法是什么,python,string,pyparsing,colon,Python,String,Pyparsing,Colon,以下是数据: C:/data/my_file.txt.c:10:0x21:name1:name2:0x10:1:OK C:/data/my_file2.txt.c:110:0x1:name2:name5:0x12:1:NOT_OK ./data/my_file3.txt.c:110:0x1:name2:name5:0x12:10:OK 我想得到这个结果 [C:/data/my_file.txt.c, 10, 0x21, name1, name2, 0x10, 1, OK] [C:/data/m

以下是数据:

C:/data/my_file.txt.c:10:0x21:name1:name2:0x10:1:OK
C:/data/my_file2.txt.c:110:0x1:name2:name5:0x12:1:NOT_OK
./data/my_file3.txt.c:110:0x1:name2:name5:0x12:10:OK
我想得到这个结果

[C:/data/my_file.txt.c, 10, 0x21, name1, name2, 0x10, 1, OK]
[C:/data/my_file2.txt.c, 110, 0x1, name2, name5, 0x12, 1, NOT_OK]
[./data/my_file3.txt.c, 110, 0x1, name2, name5, 0x12, 10, OK]
我知道如何使用一些代码或字符串拆分之类的东西来实现这一点,但我正在使用pyparsing寻找一个不错的解决方案。我的问题是文件路径的:/

附加问题我使用一些代码从记录中删除注释和其他内容,因此原始数据如下所示:

text = """C:/data/my_file.txt.c:10:0x21:name1:name2:0x10:1:OK
C:/data/my_file2.txt.c:110:0x1:name2:name5:0x12:1:NOT_OK
// comment
./data/my_file3.txt.c:110:0x1:name2:name5:0x12:10:OK
---- 
ok
"""
我去掉了//,好的,在现在解析之前

现在我还有一个问题,第一个问题:

对第一个问题的补充。到目前为止,我从一个数据文件中提取了上面的行,这非常有效。所以我逐行读取文件并解析它。但现在我发现可以使用parseFile来解析整个文件。所以我想我可以去掉一些代码,改用parseFile。因此,我想解析的文件有一个额外的页脚

C:/data/my_file.txt.c:10:0x21:name1:name2:0x10:1:OK
C:/data/my_file2.txt.c:110:0x1:name2:name5:0x12:1:NOT_OK
./data/my_file3.txt.c:110:0x1:name2:name5:0x12:10:OK: info message

-----------------------
3 Files 2 OK 1 NOT_OK
NOT_OK 
是否可以更改解析器以获得2个解析结果

结果1:

[['C:/data/my_file.txt.c', '10', '0x21', 'name1', 'name2', '0x10', '1', 'OK'],
 ['C:/data/my_file2.txt.c', '110', '0x1', 'name2', 'name5', '0x12', '1', 'NOT_OK'],
 ['./data/my_file3.txt.c', '110', '0x1', 'name2', 'name5', '0x12', '10', 'OK']]

Ignore the blank line   
Ignore this line => -----------------------
结果2:

 [['3', 'Files', 2', 'OK’, '1', 'NOT_OK'],
 ['NOT_OK’],
因此,我更改了thes代码:

    # define an expression for your file reference
one_thing = Combine(
    oneOf(list(alphas)) + ':/' +
    Word(alphanums + '_-./'))

# define a catchall expression for everything else (words of non-whitespace characters,
# excluding ':')
another_thing = Word(printables + " ", excludeChars=':')

# define an expression of the two; be sure to list the file reference first
thing = one_thing | another_thing

# now use plain old pyparsing delimitedList, with ':' delimiter
list_of_things = delimitedList(thing, delim=':')

list_of_other_things = Word(printables).setName('a')
# run it and see...
parse_ret = OneOrMore(Group(list_of_things | list_of_other_things)).parseFile("data.file")
parse_ret.pprint()
我得到了这个结果:

[['C:/data/my_file.txt.c', '10', '0x21', 'name1', 'name2', '0x10', '1', 'OK'],
['C:/data/my_file2.txt.c','110', '0x1', 'name2', 'name5', '0x12', '1', 'NOT_OK'],
['./data/my_file3.txt.c', '110', '0x1', 'name2', 'name5', '0x12', '10', 'OK', 'info message'],
['-----------------------'],
['3 Files 2 OK 1 NOT_OK'],
['NOT_OK']]
所以我可以用这个,但是有可能把结果分成两个命名的结果吗?我搜索了文件,但没有找到任何有效的。顺便问一下,有关于pyparsing的好教程吗


谢谢

请参阅嵌入注释以了解pyparsing说明:

from pyparsing import *

text = """C:/data/my_file.txt.c:10:0x21:name1:name2:0x10:1:OK
C:/data/my_file2.txt.c:110:0x1:name2:name5:0x12:1:NOT_OK
// blah-de blah blah blah
./data/my_file3.txt.c:110:0x1:name2:name5:0x12:10:OK"""

# define an expression for your file reference
one_thing = Combine(
    oneOf(list(alphas.upper())) + ':/' + 
    Word(alphanums + '_-./'))

# define a catchall expression for everything else (words of non-whitespace characters, 
# excluding ':')
another_thing = Word(printables, excludeChars=':')

# define an expression of the two; be sure to list the file reference first
thing = one_thing | another_thing

# now use plain old pyparsing delimitedList, with ':' delimiter
list_of_things = delimitedList(thing, delim=':')

parser = OneOrMore(Group(list_of_things))

# ignore comments starting with double slash
parser.ignore(dblSlashComment)

# run it and see...
parser.parseString(text).pprint()
印刷品:

[['C:/data/my_file.txt.c', '10', '0x21', 'name1', 'name2', '0x10', '1', 'OK'],
 ['C:/data/my_file2.txt.c', '110', '0x1', 'name2', 'name5', '0x12', '1', 'NOT_OK'],
 ['./data/my_file3.txt.c', '110', '0x1', 'name2', 'name5', '0x12', '10', 'OK']]
使用re:

myList = ["C:/data/my_file.txt.c:10:0x21:name1:name2:0x10:1:OK", "C:/data/my_file2.txt.c:110:0x1:name2:name5:0x12:1:NOT_OK", "./data/my_file3.txt.c:110:0x1:name2:name5:0x12:10:OK"]

for i in myList:
    newTxt =  re.sub(r':', ",", i)
    newTxt = re.sub(r',/', ":/", newTxt)
    print newTxt

所以我没有找到delimitedList和parseFile的解决方案,但我找到了一个适合我的解决方案

from pyparsing import *

data = """
C: / data / my_file.txt.c:10:0x21:name1:name2:0x10:1:OK
C: / data / my_file2.txt.c:110:0x1:name2:name5:0x12:1:NOT_OK
./ data / my_file3.txt.c:110:0x1:name2:name5:0x12:10:OK: info message

-----------------------
3 Files 2 OK 1 NOT_OK
NOT_OK
"""

if __name__ == '__main__':

# define an expression for your file reference
entry_one = Combine(
    oneOf(list(alphas)) + ':/' +
    Word(alphanums + '_-./'))

entry_two = Word(printables + ' ', excludeChars=':')
entry = entry_one | entry_two

delimiter = Literal(':').suppress()
tc_result_line = Group(entry.setResultsName('file_name') + delimiter + entry.setResultsName(
    'line_nr') + delimiter + entry.setResultsName('num_one') + delimiter + entry.setResultsName('name_one') + delimiter + entry.setResultsName(
    'name_two') + delimiter + entry.setResultsName('num_two') + delimiter + entry.setResultsName('status') + Optional(
    delimiter + entry.setResultsName('msg'))).setResultsName("info_line")

EOL = LineEnd().suppress()
SOL = LineStart().suppress()
blank_line = SOL + EOL

tc_summary_line = Group(Word(nums).setResultsName("num_of_lines") + "Files" + Word(nums).setResultsName(
    "num_of_ok") + "OK" + Word(nums).setResultsName("num_of_not_ok") + "NOT_OK").setResultsName(
    "info_summary")
tc_end_line = Or(Literal("NOT_OK"), Literal('Ok')).setResultsName("info_result")

# run it and see...
pp1 = tc_result_line | Optional(tc_summary_line | tc_end_line)
pp1.ignore(blank_line | OneOrMore("-"))

result = list()
for l in data.split('\n'):
    result.append((pp1.parseString(l)).asDict())
# delete empty results
result = filter(None, result)

for r in result:
    print(r)

pass
结果:

{'info_line': {'file_name': 'C', 'num_one': '10', 'msg': '1', 'name_one':   '0x21', 'line_nr': '/ data / my_file.txt.c', 'status': '0x10', 'num_two': 'name2', 'name_two': 'name1'}}
{'info_line': {'file_name': 'C', 'num_one': '110', 'msg': '1', 'name_one': '0x1', 'line_nr': '/ data / my_file2.txt.c', 'status': '0x12', 'num_two': 'name5', 'name_two': 'name2'}}
{'info_line': {'file_name': './ data / my_file3.txt.c', 'num_one': '0x1', 'msg': 'OK', 'name_one': 'name2', 'line_nr': '110', 'status': '10', 'num_two': '0x12', 'name_two': 'name5'}}
{'info_summary': {'num_of_lines': '3', 'num_of_ok': '2', 'num_of_not_ok': '1'}}
{'info_result': ['NOT_OK']}

您可以更改分隔符或引用与语法冲突的区域吗?如果字段的数量是固定的,并且在第一个元素中总是出现额外的冒号,快速解决方法可能是使用maxslit,例如line.rsplit:,maxslit=NUM_of_字段。我想使用so@rogalski,我知道如何用您解释的方式解决问题, thanks@AIG不,我不能改变。谢谢,保罗,这正是我想要的方式。最后一个问题-有没有办法添加一个模式来忽略整条线?举个例子,如果在两个记录中间有一个注释看到最新的变化。谢谢,这也是一个很好的解决方案,但是我想使用PyPrScript。