我的re.sub语句挂断了

时间:2014-07-14 19:53:44

标签: python regex

我是一名Python(和正则表达式)新手,在统计软件包(SAS& Stata)之外的编程经验相对较少。到目前为止,我已经通过使用Python教程和有关stackoverflow的其他问题的答案,但我已经陷入困境。我在Mac OS X上运行Python 3.4。

我已经编写了一个下载和解析美国证券交易委员会文件的脚本。该脚本有四个主要步骤:

  1. 打开URL并将内容加载到字符串变量
  2. 使用BeautifulSoup删除HTML编码
  3. 使用正则表达式语句删除其他编码(如jpg定义,嵌入式zip文件等)
  4. 保存生成的文本文件。
  5. 我的目标是尽可能多地删除"非文字"保存到本地驱动器之前,每个文件中的信息尽可能多。我写了另一个脚本,我在那里对剩余文本进行实际分析。

    我在至少一份文件中遇到了第3步的问题。导致挂断的行是:

    _content1 = re.sub(r'(?i).*\.+(xls|xlsx|pdf|zip|jpg|gif|xml)+?[\d\D]+?(end)',r'',_content1)
    

    其中_content是一个字符串变量,包含SEC文件的内容。正则表达式语句应该捕获以一个以文件扩展名结尾的行开头的块(xls,pdf等),并以单词" end结束。"

    以上代码整年都运作良好'值得提交(即,我已经分析了2001年和2002年的所有问题),但我的剧本在2013年的一个特定文件中被挂起(http://www.sec.gov/Archives/edgar/data/918160/0000918160-13-000024.txt)。我不确定如何调试,因为我没有收到任何错误消息。该脚本只挂在那一行代码上(我已经在前后使用print语句验证了这一点)。有趣的是,如果我用以下代码替换上面的代码:

    _content1 = re.sub(r'(?i)begin*.*(xls|xlsx|pdf|zip|jpg|gif|xml)+?[\d\D]+?(end)',r'',_content1)
    

    然后一切正常。遗憾的是,文件中的某些嵌入式文件并非始于"开始" (比如zip文件),所以它不适合我。

    我希望其中一位常驻专家可以在我的正则表达式替换声明中找出可能导致问题的内容,因为通过链接的SEC备案进行匹配可能是不可行的(至少我不知道从哪里开始)。非常感谢任何帮助。

    谢谢, JRM

    编辑:

    我能够通过使用以下REGEX来使我的脚本工作:

    _content1 = re.sub(r'(?i)begin|\n+?.+?(xls|xlsx|pdf|zip|jpg|gif|xml)+?[\d\D]+?(end)',r'\n',_content1)
    

    这似乎正在实现我想要的东西,但我仍然很好奇为什么如果有人有解决方案,原件没有用。

2 个答案:

答案 0 :(得分:0)

尝试使用以下REGEX

_content1 = re.sub(r'(?i).*?\.+(xls|xlsx|pdf|zip|jpg|gif|xml)+?[\d\D]+?(end)',r'',_content1)

我已将您的*操作转换为*?这是非贪婪的,很可能是你想要的。

答案 1 :(得分:0)

我认为你最大的问题是缺乏锚点。您的原始正则表达式以.*开头,可以开始在任何地方进行匹配,并且不会停止匹配,直到它到达换行符或文本末尾。然后它开始回溯,一次返回一个字符,试图匹配模式的第一个可证伪组件:点和文件扩展名的字母。

所以它从文件的开头开始并消耗了数千个字符,只是在放弃之前一直回溯到开头。然后它向前碰撞并从第二个角色开始做同样的事情。再次从第三个角色,从第四个角色,依此类推。我知道它似乎非常密集,但这是我们为正则表达式的力量和紧凑性所做的权衡。

试试这个正则表达式:

r"(?im)^[^<>\n]+\.(?:xlsx?|pdf|zip|jpg|gif|xml)\n(?:(?!end$)\S+\n)+end\n"

多线模式下的起始锚点(^)确保匹配只能从一行的开头开始。我在行的第一部分使用了[^<>\n]+,因为我正在使用您链接到的文件;如果您已删除所有HTML和XML标记,则可以使用.+代替。

然后我使用(?:(?!end$).+\n)+来匹配一个或多个不完全由end组成的完整行。它可能比你的[\d\D]+?更有效,但最重要的区别是,当我匹配end时,我知道它在行的开头(并且$确保它在行尾。)