代码之家  ›  专栏  ›  技术社区  ›  Scott Saunders

阅读文本的算法或模式

  •  6
  • Scott Saunders  · 技术社区  · 17 年前

    我的公司有一个客户跟踪不同地点不同公司产品的价格。这些信息进入数据库。

    这些公司每天通过电子邮件将价格发送给我们的客户,当然,电子邮件的格式也各不相同。不可能让任何一家公司改变他们的格式——他们不会这么做。

    有些看起来像这样:

        This is example text that could be many lines long...
    
        Location 1
        Product 1     Product 2     Product 3
        $20.99        $21.99        $33.79
    
        Location 2
        Product 1     Product 2     Product 3
        $24.99        $22.88        $35.59
    

    其他人看起来有点像这样:

        PRODUCT       PRICE    + / -
        ------------  -------- -------
        Location 1
        1             2007.30 +048.20
        2             2022.50 +048.20
    
        Maybe some multiline text here about a holiday or something...
    
        Location 2
        1             2017.30 +048.20
        2             2032.50 +048.20
    

    对于我们来说,查看电子邮件并确定在哪个位置哪个产品的价格是无关紧要的。但对于我们的代码来说并不是这样。因此,我正试图找到一个更灵活的解决方案,并希望您对采取何种方法提出建议。我对任何东西都持开放态度,从正则表达式到神经网络,我将学习使这项工作发挥作用所需要的东西,我只是不知道我需要学习什么。这是一个lex/解析问题吗?更类似于OCR?

    代码不必自己找出所有的格式。这些电子邮件有几种主要的“风格”,就像上面提到的那样。我们确实需要代码具有足够的灵活性,以使新的产品线或空白或其他内容不会使文件不可解析。

    3 回复  |  直到 17 年前
        1
  •  7
  •   David Raznick    17 年前

    对于这些类型的任务,我将使用pyparsing,因为它具有完整lr解析器的功能,但没有难以定义的语法和非常好的辅助函数。代码也很容易阅读。

    from pyparsing import *
    
    aaa ="""    This is example text that could be many lines long...
                 another line
    
        Location 1
        Product 1     Product 2     Product 3
        $20.99        $21.99        $33.79
    
        stuff in here you want to ignore
    
        Location 2
        Product 1     Product 2     Product 3
        $24.99        $22.88        $35.59 """
    
    result = SkipTo("Location").suppress() \  
    # in place of "location" could be any type of match like a re.
             + OneOrMore(Word(alphas) + Word(nums)) \
             + OneOrMore(Word(nums+"$.")) \
    
    all_results = OneOrMore(Group(result))
    
    parsed = all_results.parseString(aaa)
    
    for block in parsed:
        print block
    

    这将返回一个列表列表。

    ['Location', '1', 'Product', '1', 'Product', '2', 'Product', '3', '$20.99', '$21.99', '$33.79']
    ['Location', '2', 'Product', '1', 'Product', '2', 'Product', '3', '$24.99', '$22.88', '$35.59']
    

    我不知道在其他语言中是否有对等词。

        2
  •  0
  •   nik    17 年前

    您已经为文本文件提供了两个模式示例。

    类似于:AWK、sed、grep和bash脚本。


    第一个样本中有一个模式,

    1. 部分以关键字开头 Location [数字]
      • 第二行有描述产品名称的列
      • 第三行有列,列中有产品的价格

    每个部分可以有不同数量的产品。
    每个文件可以有不同数量的节。
    产品和价格始终在某个部分的指定行上。
    空格分隔标识 (product,price) 列关联。


    收集到的数据可能会被纳入数据库。

        3
  •  0
  •   user447688 user447688    17 年前

    我知道我会在这里使用正则表达式。三个或四个表达式可以驱动每种电子邮件格式的解析逻辑。