使用Java/Python从大型结构化文件中提取数据

0 投票
5 回答
1484 浏览
提问于 2025-04-16 04:46

我有一个很大的文本文件(大约100MB),需要解析里面的信息。我想找一种高效的方法来完成这个任务。这个文件是按块结构组织的:

Mon, 01 Jan 2010 01:01:01
  Token1 = ValueXYZ
  Token2 = ValueABC
  Token3 = ValuePQR
  ...
  TokenX = Value123

Mon, 01 Jan 2010 01:02:01
  Token1 = ValueXYZ
  Token2 = ValueABC
  Token3 = ValuePQR
  ...
  TokenY = Value456

有没有什么库可以帮助解析这个文件?(可以是Java、Python,或者任何命令行工具)

补充:我知道这个问题有点模糊,但关键不是如何读取文件、用正则表达式解析等等。我更想要的是一些关于性能的库或工具建议。例如,Antlr可能是一个选择,但这个工具会把整个文件加载到内存中,这样不好。

谢谢!

5 个回答

0

我觉得这些数据结构得非常好,所以不需要外部的工具来处理。写一个解析器可能只需要几分钟,而且运行起来也会很快。

0

通常,我们会这样做。re库基本上可以处理这个问题。使用生成器函数可以应对这种嵌套的结构。

def gen_blocks( my_file ):
    header_pat= re.compile( r"\w3, \d2 \w3 \d4 \d2:\d2:\d2" )
    detail_pat = re.compile( r"\s2\S*\s+=\s+\S*" )
    lines = []
    for line in my_file:
        hdr_match=header_pat.match( line )
        if hdr_match:
            if lines:
                yield header, lines
                lines= []
             header= hdr.match.groups()
             continue
         dtl_match= detail_pat.match( line )
         if dtl_match:
             lines.append( dtl_match.groups() )
             continue
         # Neither kind of line, maybe blank or maybe an error
     if lines:
         yield header, lines

for header, lines in gen_blocks( some_file ):
    print header, lines
0

为了高效地解析文件,特别是处理大文件时,你可以使用awk。下面是一个例子:

$ awk -vRS= '{print "====>" $0}' file
====>Mon, 01 Jan 2010 01:01:01
  Token1 = ValueXYZ
  Token2 = ValueABC
  Token3 = ValuePQR
  ...
  TokenX = Value123
====>Mon, 01 Jan 2010 01:02:01
  Token1 = ValueXYZ
  Token2 = ValueABC
  Token3 = ValuePQR
  ...
  TokenY = Value456
====>Mon, 01 Jan 2010 01:03:01
  Token1 = ValueXYZ
  Token2 = ValueABC
  Token3 = ValuePQR

如你所见,箭头之间的每一条记录现在都是一个完整的块,从“====>”箭头开始到下一个箭头结束(通过将记录分隔符RS设置为空格)。接下来你可以设置字段分隔符,比如换行符。

$ awk -vRS= -vFS="\n" '{print "====>" $1}' file
====>Mon, 01 Jan 2010 01:01:01
====>Mon, 01 Jan 2010 01:02:01
====>Mon, 01 Jan 2010 01:03:01

在上面的例子中,每个第一字段都是日期/时间戳。比如要获取“token1”,你可以这样做:

$ awk -vRS= -vFS="\n" '{for(i=1;i<=NF;i++) if ($i ~/Token1/){ print $i} }' file
  Token1 = ValueXYZ
  Token1 = ValueXYZ
  Token1 = ValueXYZ

撰写回答