【问题标题】:Python: Reading part of a text filePython:读取文本文件的一部分
【发布时间】:2009-06-08 23:26:03
【问题描述】:

大家好

我是 python 和编程的新手。我需要读取大文本文件的块,格式如下所示:

<word id="8" form="hibernis" lemma="hibernus1" postag="n-p---nb-" head-"7" relation="ADV"/>

我需要formlemmapostag 信息。例如以上我需要hibernishibernus1n-p---nb-

我如何告诉python读取直到它到达表单,向前读取直到到达引号",然后读取引号"hibernis"之间的信息?真的在为此苦苦挣扎。

到目前为止,我的尝试是删除标点符号,拆分句子,然后从列表中提取我需要的信息。虽然无法让 python 遍历整个文件,但我只能让它工作 1 行。我的代码如下:

f=open('blank.txt','r')
quotes=f.read()
noquotes=quotes.replace('"','')
f.close()

rf=open('blank.txt','w')
rf.write(noquotes)
rf.close()   

f=open('blank.txt','r')
finished = False
postag=[]
while not finished:
   line=f.readline()
   words=line.split()
   postag.append(words[4])
   postag.append(words[6])
   postag.append(words[8])              
   finished=True

感谢任何反馈/批评

谢谢

【问题讨论】:

    标签: python


    【解决方案1】:

    如果是XML,使用ElementTree解析:

    from xml.etree import ElementTree
    
    line = '<word id="8" form="hibernis" lemma="hibernus1" postag="n-p---nb-" head="7" relation="ADV"/>'
    
    element = ElementTree.fromstring(line)
    

    对于每个 XML 元素,您可以轻松提取名称和所有属性:

    >>> element.tag
    'word'
    >>> element.attrib
    {'head': '7', 'form': 'hibernis', 'postag': 'n-p---nb-', 'lemma': 'hibernus1', 'relation': 'ADV', 'id': '8'}
    

    因此,如果您有一个包含一堆 word XML 元素的文档,则类似这样的操作将从每个元素中提取您想要的信息:

    from xml.etree import ElementTree
    
    XML = '''
    <words>
        <word id="8" form="hibernis" lemma="hibernus1" postag="n-p---nb-" head="7" relation="ADV"/>
    </words>'''
    
    root = ElementTree.fromstring(XML)
    
    for element in root.findall('word'):
        form = element.attrib['form']
        lemma = element.attrib['lemma']
        postag = element.attrib['postag']
    
        print form, lemma, postag
    

    如果您只有一个文件名,请使用 parse() 而不是 fromstring()

    【讨论】:

      【解决方案2】:

      我建议使用正则表达式模块:re

      也许是这样的?

      #!/usr/bin/python
      import re
      
      if __name__ == '__main__':
          data = open('x').read()
          RE = re.compile('.*form="(.*)" lemma="(.*)" postag="(.*?)"', re.M)
          matches = RE.findall(data)
          for m in matches:
              print m
      

      这确实假设&lt;word ...&gt; 行都在一行上,并且每个部分都按照确切的顺序进行,并且您不需要处理完整的 xml 解析。

      【讨论】:

      • 感谢回溯。刚刚尝试了您的代码,它正是我需要的。非常感谢您的帮助。我一开始确实尝试了 re 模块并有以下表达式:for line in f: if re.match("(.*)(f|1)orm(.*)", line): print >>rfformat, line ,
      • 但愚蠢地放弃了该方法并采用了列表方法。我现在要研究 re 模块并确保我知道你的代码在做什么
      • 正则表达式(以及下面我的)对标签的排序做了一个假设,这可能并非对所有条目都有效
      • 用正则表达式解析 XML 很少是个好主意。例如,如果属性用单引号分隔,此 RE 将失败,并且它不会扩展文本中的字符实体,而应用程序可能需要它。
      • 如果你的问题是读取 XML 并且你尝试使用正则表达式,那么现在你有 3 个问题:原来的,试图强制正则表达式来解决它,甚至不知道你走错了路.
      【解决方案3】:

      您的文件是正确的 XML 吗?如果是这样,请尝试使用 SAX 解析器:

      import xml.sax
      class Handler (xml.sax.ContentHandler):
         def startElement (self, tag, attrs):
             if tag == 'word':
                 print 'form=', attrs['form']
                 print 'lemma=',attrs['lemma']
                 print 'postag=',attrs['postag']
      
      ch = Handler ()
      f = open ('myfile')
      xml.sax.parse (f, ch)
      

      (这很粗略……可能并不完全正确)。

      【讨论】:

      • 您好,文件都是 xml,必须查看 sax 解析器以及下面提到的漂亮汤。可能会使事情变得简单得多。感谢您的帮助
      • 请记住,BeautifulSoup 不是标准 python 发行版的一部分(以防您不得不在无权添加软件包的环境中使用此脚本)。
      【解决方案4】:

      除了通常的 RegEx 答案,由于这似乎是 XML 的一种形式,您可以尝试一下 BeautifulSoup (http://www.crummy.com/software/BeautifulSoup/)

      它非常易于使用,并且可以在 HTML/XML 等内容中找到标签/属性,即使它们不是“格式正确”。也许值得一瞧。

      【讨论】:

        【解决方案5】:

        手动解析 xml 通常是 错误的事情。一方面,您的代码 如果有一个逃跑的会打破 引用任何属性。 从 xml 中获取属性 解析器可能更干净,更少 容易出错。

        如果您的行与格式不匹配,这样的方法也可能会在解析整个文件时遇到问题。您可以通过创建 parseline 方法(类似

        def parse (line):
              try: 
                  return parsed values here
                except: 
        

        您还可以使用过滤器和映射功能简化此操作:

        lines = filter( lambda line: parseable(line), f.readlines())
        values = map (parse, lines)
        

        【讨论】:

          【解决方案6】:

          只是为了突出您的问题:

          finished = False
          counter = 0
          while not finished:
             counter += 1
             finished=True
          print counter
          

          【讨论】:

          • 其实你的答案是最好的。 :) 所有其他人都不关心更正代码。
          【解决方案7】:

          使用正则表达式,这是要点(您可以执行 file.readline() 部分):

          import re
          line = '<word id="8" form="hibernis" lemma="hibernus1" postag="n-p---nb-" head-"7" relation="ADV"/>'
          r = re.compile( 'form="([^"]*)".*lemma="([^"]*)".*postag="([^"]*)"' )
          match = r.search( line )
          print match.groups()
          
          >>> 
          ('hibernis', 'hibernus1', 'n-p---nb-')
          >>> 
          

          【讨论】:

            【解决方案8】:

            首先,不要花费大量时间重写文件。这通常是浪费时间。清理和解析标签的处理速度非常快,您会非常高兴地一直使用源文件。

            source= open( "blank.txt", "r" )
            for line in source:
                # line has a tag-line structure
                # <word id="8" form="hibernis" lemma="hibernus1" postag="n-p---nb-" head-"7" relation="ADV"/>
                # Assumption -- no spaces in the quoted strings.
                parts = line.split()
                # parts is [ '<word', 'id="8"', 'form="hibernis"', ... ]
                assert parts[0] == "<word"
                nameValueList = [ part.partition('=') for part in parts[1:] ]
                # nameValueList is [ ('id','=','"8"'), ('form','=','"hibernis"'), ... ]
                attrs = dict( (n,eval(v)) for n, _, v in nameValueList )
                # attrs is { 'id':'8', 'form':'hibernis', ... }
                print attrs['form'], attrs['lemma'], attrs['posttag']
            

            【讨论】:

            • 这里真的需要 eval 吗? strip('"') 不是更好的选择吗?
            • @SilentGhost:这是六中之一,六种其他情况。有些人喜欢说“eval 是邪恶的”——这在很大程度上是毫无意义的。但是,示例中显示的字符串似乎是一个有效的 Python 字符串也是一个巧合。可能有转义字符和 Python 不同,因为非 Python 字符串语法导致 eval 无效。
            【解决方案9】:

            哇,你们真快:) 如果你想要一个列表的所有属性(并且顺序是已知的),那么你可以使用这样的东西:

            import re
            print re.findall('"(.+?)"',INPUT)
            

            INPUT 是这样的一行:

            <word id="8" form="hibernis" lemma="hibernus1" postag="n-p---nb-" head="7" relation="ADV"/>
            

            打印出来的列表是:

            ['8', 'hibernis', 'hibernus1', 'n-p---nb-', '7', 'ADV']
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2020-09-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-05-17
              • 2012-05-28
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多