【问题标题】:How to parse text file using unique delimiters?如何使用唯一分隔符解析文本文件?
【发布时间】:2017-05-26 16:06:37
【问题描述】:

Spyder 2.x 上的 Python 3.5.2

我有数千个文本文件,它们采用以下半结构化格式。

下面是一个文件one.txt:

Goodsign:       Klisti upto 15:57         Bad Omen:     Gated zone      
 
 
Dusk Attack:        Uptime      Dusk Rest:      Winters

下面是第二个文件 second.txt

Goodsign:       Kukul upto 12:60          Bad Omen:     Open zone       
 
 
Dusk Attack:        Downtime        Dusk Rest:      Summers Daring Tribe: Mojars of Moana

现在我想解析这两个文件并获取标签 Goodsign 的值:在 one.txt 中为“Klisti upto 15:57”,在第二种情况下为“Kukul upto 12:60”。

对于下一组变量,再次使用相同的 Bad Omen:获取值“Gated zone”和第二个情况 Bad Omen:“Open zone”。

对于下一组变量,再次忽略 &nbsp 并获取标签“Dusk Attack:”的值,对标签“Dusk Rest:”重复相同的操作

问题除了:分隔符之外,值之间似乎有一个制表符分隔符,例如 Downtime Dusk Rest: there is a gap "" is this tab or how to parse this kind of text?

我尝试实现下面的代码,但如何仅用于分隔符“Dusk Rest:”,但它给出了之后的所有值。我只需要重视“停机时间”,而它给了我“停机时间黄昏休息:萨默斯大胆部落:莫阿纳的莫哈尔”:

f = open('one.txt', 'r')
lines = f.readlines()
f.close()
searchtxt="Dusk Rest:"
for i, line in enumerate(lines):    
    if searchtxt in line and i+1 < len(lines):
    #print(lines[i+1])
    print(line)
    break

非常感谢您的宝贵回答!

【问题讨论】:

  • 每个文件是否有多个这样的块?
  • 是的,每个文件单个块在同一个文件中不重复“黄昏休息:”只出现一次。

标签: python python-3.x parsing text-files delimiter


【解决方案1】:

处理这些文件的另一种方法是在正则表达式上拆分它们,也许像这样。

有用的信息位似乎被至少两个连续的空白项分开。我们可以分开这些。同时,如果我们可以假设它们始终是&amp;nbsp;\s 的形式,我们可以安排消除前导的无退格 HTML 元素。否则,他们将不得不分开对待。拆分字段后,我们可以使用list 类型的index 方法在拆分项中查找字段名称以形成值。 (这允许我们在某个地方不恰当地拆分文件的内容;我们可以将一个字段重新粘合在一起。

import re

for file_name in ['one.txt', 'second.txt']:
    print (file_name)
    with open(file_name) as f:
        content = f.read()
        items = re.split(r'\s{2,}(?:&nbsp;\s)*', content)
        print (items)
        results = {}
        results['Goodsign:'] = ' '.join(items[1: items.index('Bad Omen:')])
        results['Bad Omen:'] = ' '.join(items[1+items.index('Bad Omen:'): items.index('Dusk Attack:')])
        results['Dusk Rest:'] = ' '.join(items[1+items.index('Dusk Attack:'):])
        results['Dusk Attack:'] = ' '.join(items[1+items.index('Dusk Attack:'): items.index('Dusk Rest:')])
        results['Dusk Rest:'] = ' '.join(items[1+items.index('Dusk Rest:'):])
        for result in results:
            print (result, results[result])

这是输出:

one.txt
['Goodsign:', 'Klisti upto 15:57', 'Bad Omen:', 'Gated zone', 'Dusk Attack:', 'Uptime', 'Dusk Rest:', 'Winters']
Bad Omen: Gated zone
Goodsign: Klisti upto 15:57
Dusk Attack: Uptime
Dusk Rest: Winters
second.txt
['Goodsign:', 'Kukul upto 12:60', 'Bad Omen:', 'Open zone', 'Dusk Attack:', 'Downtime', 'Dusk Rest:', 'Summers']
Bad Omen: Open zone
Goodsign: Kukul upto 12:60
Dusk Attack: Downtime
Dusk Rest: Summers

【讨论】:

  • 您的代码仅在构建项目时才起作用,结果开始出现错误,因此我创建了自己的代码,但会接受您的答案,因为它可能对未来有所帮助。 @比尔·贝尔
  • 如果您提供引发错误的项目,我可以尝试诊断错误。
【解决方案2】:

假设您的字符串由两个示例组成:

>>> txt="""\
... Goodsign:       Klisti upto 15:57         Bad Omen:     Gated zone      
... &nbsp;
... &nbsp;
... Dusk Attack:        Uptime      Dusk Rest:      Winters
... Goodsign:       Kukul upto 12:60          Bad Omen:     Open zone       
... &nbsp;
... &nbsp;
... Dusk Attack:        Downtime        Dusk Rest:      Summers
... """

您可以使用正则表达式来获取以下特定字段的值:

>>> import re
>>> pat1=r'^Goodsign:[ \t]*(.*?)[ \t]*(?=Bad Omen:)'
>>> pat2=r'Bad Omen:[ \t]*(.*?)[ \t]*\n'
>>> re.findall(pat1, txt, re.M)
['Klisti upto 15:57', 'Kukul upto 12:60']
>>> re.findall(pat2, txt)
['Gated zone', 'Open zone']

等等。

如果字段是 \t 分隔的(您的示例不是这样),您的正则表达式将变得非常容易编写。


根据评论编辑

Python 3 是强类型的。您的错误基于 items 被用作字符串。

如果您执行以下操作,它应该可以工作:

for fn in [something that generates a list of file names...]
    with open(fn) as f:
        txt=f.read()
        m=re.search(pat1, txt, re.M)
        if m:
            print(m.group(1))

【讨论】:

  • 您的代码的问题是 txt 变量是字符串格式,而当我读取数据时它是列表格式,所以下面给出了错误类型(项目) str1 = ''.join(项目)打印(str1) pat1=r'^Nakshatra:[ \t]*(.*?)[ \t]*(?=Yoga:)' re.findall(pat1, items, re.M) TypeError: expected string or bytes - 类似 findall() 函数中的对象当我将列表转换为字符串时出现上述错误你知道如何解决吗?
【解决方案3】:

我不知道您是否正确理解了您的问题...但我认为您正在寻找标签的转义序列 \t。我想你知道如何使用它。

【讨论】:

  • 不,在这种情况下我不知道如何使用转义序列'\t'和':'分隔符
猜你喜欢
  • 1970-01-01
  • 2019-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多