用于在两个常量字符串之间搜索变量字符串

时间:2016-08-26 22:16:57

标签: python

import re

infile = open('document.txt','r')
outfile= open('output.txt','w')
copy = False
for line in infile:

    if line.strip() == "--operation():":
        bucket = []
        copy = True

    elif line.strip() == "StartOperation":
        for strings in bucket:
            outfile.write( strings + ',')
        for strings in bucket:
            outfile.write('\n')
        copy = False

    elif copy:
        bucket.append(line.strip()

CSV格式如下:

id,          name,                poid,         error
5896, AutoAuthOSUserSubmit,     900105270,      0x4002

我的日志文件有几个部分,以==== START ====开头,以==== END ====结尾。我想在--operation():StartOperation之间提取字符串。例如,AutoAuthOSUserSubmit.我还想从行poid中提取poid: 900105270, poidLen: 9值。最后,我想提取返回值,例如0x4002如果在Roll back all updates之后找到它。

如果StartEnd不在同一行,我甚至无法提取原始文本。我该怎么做呢?

这是一个带有两段的LOG提取示例:

-- 08/24 02:07:56 [mds.ecas(5896) ECAS_CP1] **==== START ====**
open file /ecas/public/onsite-be/config/timer.conf failed
INFO 08/24/16 02:07:56  salt1be-d1-ap(**5896**/0)  main.c(780*****):--operation(): AutoAuthOSUserSubmit. StartOperation*****
INFO 08/24/16 02:07:56  salt1be-d1-ap(5896/0)  main.c(784):--Client Information: Request from host 'malt-d1-wb' process id 12382.
DEBUG 08/24/16 02:07:56  salt1be-d1-ap(5896/0)  TOci.cc(571):FetchServiceObjects: ServiceCert.sql
DEBUG 08/22/16 23:15:53  pepper1be-d1-ap(2680/0)  vsserviceagent.cpp(517):Generate Certificate 2: c1cd00d5c3de082360a08730fef9cd1d
DEBUG 08/22/16 23:15:53  pepper1be-d1-ap(2680/0)  junk.c(1373):GenerateWebPin : poid: **900105270**, poidLen: 9
DEBUG 08/22/16 23:15:53  pepper1be-d1-ap(2680/0)  junk.c(1408):GenerateWebPin : pinStr 
DEBUG 08/24/16 02:07:56  salt1be-d1-ap(5896/0)  uaadapter_vasco_totp.c(275):UAVascoTOTPImpl.close() -- Releasing Adapter Context
DEBUG 08/22/16 23:15:53  pepper1be-d1-ap(2680/0)  vsenterprise.cpp(288):VSEnterprise::Engage returns 0x4002 - Unknown error code **(0x4002)**
ERROR 08/22/16 23:15:53  pepper1be-d1-ap(2680/0)  vsautoauth.cpp(696):OSAAEndUserEnroll: error occurred. **Roll back** all updates!
INFO 08/24/16 02:07:56  salt1be-d1-ap(5896/0)  uaotptokenstoreqmimpl.cpp(199):Close token store
INFO 08/24/16 02:07:56  salt1be-d1-ap(5896/0)  main.c(990):-- EndOperation
-- 08/24 02:07:56 [mds.ecas(5896) ECAS_CP1] **==== END   ====**
    OPERATION = AutoAuthOSUserSubmit, rc = 0x0 (0)
    SYSINFO Elapse = 0.687, Heap = 1334K, Stack = 64K

2 个答案:

答案 0 :(得分:1)

看起来您只是想在LOG文档中查找字符串并尝试使用关键字解析字符行。您可以逐行进行当前正在执行的操作,或者您可以浏览一次文档(假设LOG文档永远不会变大)并将每个后续行添加到现有字符串中。

查看此信息以查找子字符串 http://www.tutorialspoint.com/python/string_index.htm< ---用于查找字符串在另一个字符串中的位置,这将帮助您确定起始索引和结束索引。完成后,您可以提取所需信息。

检查此问题是否存在CSV问题 http://www.tutorialspoint.com/python/string_split.htm< ---用于分割特定字符周围的字符串,即“,”,用于CSV文件。

Does Python have a string contains substring method?比使用strip()方法的当前方法更有用

希望这会指出你正确的方向!

答案 1 :(得分:1)

这看起来像正则表达式的工作!实际上有几个。值得庆幸的是,在这种情况下使用起来并不复杂。

有2个主要观察结果会让我选择正则表达式而不是其他东西:

  1. 需要从两个已知常量值之间提取一位变量文本
  2. 对于不同的字符串,需要多次遵循相同的模式
  3. 您可以尝试这样的事情:

    import re
    
    def capture(text, pattern_string, flags=0):
        pattern = re.compile(pattern_string, flags)
        match = pattern.search(text)
        if match:
            output = match.group(1)
            print '{}\n'.format(output)
            return output
        return ''
    
    if __name__ == '__main__':
        file = read_my_file()
    
        log_pattern = "\*\*==== START ====\*\*(.+)\*\*==== END   ====\*\*"
        log_text = capture(file, log_pattern, flags=re.MULTILINE|re.DOTALL)
    
        op_pattern = "--operation\(\): (.+). StartOperation\*\*\*\*\*"
        op_name = capture(log_text, op_pattern)
    
        poid_pattern = "poid: \*\*([\d]+)\*\*, poidLen: "
        op_name = capture(log_text, poid_pattern)
    
        retcode_pattern = "Unknown error code \*\*\((.+)\)\*\*.+\*\*Roll back\*\* all updates!"
        retcode = capture(log_text, retcode_pattern, flags=re.MULTILINE|re.DOTALL)
    

    这种方法基本上将问题分成几个很大程度上独立的步骤。我在每个正则表达式中使用捕获组 - 像(.+)([\d]+)这样的parens - 在长字符串的常量字符之间。 multiline和dotall标志允许您轻松处理文本中的换行符,并像处理字符串的任何其他部分一样处理它们。

    我也在这里做了一个很大的假设,那就是你的日志不是大文件,可能是几百兆的顶部。请注意read_my_file()的调用 - 而不是尝试一次解决这个问题,我选择读取整个文件并在内存中工作。如果文件变得非常大,或者你正在构建一个会获得大量流量的应用程序,这可能是一个坏主意。

    希望这有帮助!