Python版本3.3迭代正则表达式冻结

时间:2014-06-02 18:54:04

标签: python regex freeze

我正在尝试使用正则表达式匹配文本文件中的一行,但每次调用pattern.finditer(行)时,程序都会冻结。程序的另一部分将一个文本块传递给formatLine方法。文本格式如下:

line="8,6,14,32,42,4,4,4,3,5,3,3,4,2,2,2,1,2,3,2,1,3,4,2,3,10,false,false,false,false,true,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,1,2,1,2,4,"

def formatLine(line):
    print(line)
    print("----------")
    commas=len(line.split(","))
    timestamp="(\d+,){5}"
    q1="([1-5,]+){20}"
    q2="([1-5,]+)"
    q3="(true,|false,){10}"
    q4="(true,|false,){6}"
    q5="(true,|false,){20}"
    q6="([1-5,]+){5}"
    pattern=re.compile(timestamp+q1+q2+q4+q5)
    print("here")
    response=pattern.finditer(line)
    for ans in response:
        numPattern+=1
        #write to file for each instance of ans

    #these check that the file is valid
    print("here")
    #more code, omitted

formatLine(line)#call method here

第一次和第二次打印报表正确打印,但从不打印“此处”字样。任何人都知道为什么它会冻结和/或我能做些什么来解决它?

编辑:阅读评论后,我意识到一个更好的问题是:如何改进上面的正则表达式以获得下面的模式?我刚刚开始python(昨天)并且一直在重复阅读python正则表达式教程。 每个值(真或假或数字用逗号分隔).....我从中提取的文件是CSV。

-Pattern我想得到:

  • 5位数(每位数为0-60)
  • 20位数(每位数为1-5)
  • 36真或假(可能是任何真或假的安排)
  • 5位数(每位数为1-5)

  • 2 个答案:

    答案 0 :(得分:1)

    您的表达式,尤其是([1-5,]+){20}部分导致catastrophic backtracking。它并没有挂起,只是忙着解决这个难题:"让我的数字重复N次重复20次"。你可能最好用([1-5]+,){20}替换它,尽管我不认为你的方法是可行的。只需用逗号分隔字符串,然后从列表中切片。

    根据您的更新,这似乎是正确的模式:

    pattern = r"""(?x)
    
        ([0-9], | [1-5][0-9], | 60,) {5}  # 5 numbers (each number is 0-60)
    
        ([1-5],) {20}          # 20 digits (each digit is 1-5)
    
        (true,|false,) {36}    # 36 true or false (may be in any arrangement of true or false)
    
        ([1-5],) {20}          # 20 digits (each digit is 1-5)
    
    """
    

    答案 1 :(得分:0)

    当然,这就是csv模块的设计目标,不需要正则表达式:

    line="8,6,14,32,42,4,4,4,3,5,3,3,4,2,2,2,1,2,3,2,1,3,4,2,3,10,false,false,false,false,true,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,1,2,1,2,4"
    
    from io import StringIO   # this allows the string to act like a file 
    f=StringIO(line)          # -- just use a file
    
    ### cut here
    import csv
    
    reader=csv.reader(f)
    
    for e in reader:
        # then just slice up the components:
        q1=e[0:5]        # ['8', '6', '14', '32', '42']
        q2=e[6:26]       # ['4', '4', '3', '5', '3', '3', '4', '2', '2', '2', '1', '2', '3', '2', '1', '3', '4', '2', '3', '10']
        q3=e[27:53]      # ['false', 'false', 'false', 'true', 'false', 'false', 'true', 'false', 'false', 'false', 'false', 'false', 'false', 'false', 'false', 'false', 'false', 'false', 'false', 'false', 'false', 'false', 'false', 'false', 'false', 'false']
        q4=e[54:]        # ['2', '1', '2', '4']
    

    然后,您可以根据需要验证每个部分。