Python正则表达式在长路径中获取文件名

时间:2011-04-28 15:07:58

标签: python regex file

我需要分析一些日志文件,它看起来如下,我想检索3部分数据,

  1. 时间
  2. 目录的一部分,在这种情况下,它将是输入文件中的ABC和DEF。
  3. 输入文件中的文件名,即2C.013000000B.dat,20100722B.TXT,20100722D1-XYZ.TXT和2C.250B。
  4. 我使用这个正则表达式,但它未能获得第三部分。

    (\d\d:\d\d:\d\d).*(ABC|DEF).*\\(\d\w\.?\w\..*)\soutput.*
    

    任何建议都将受到赞赏。

    08:38:36   TestModule - [INFO]result success !! ftp_site=ftp.test.com file_dir=CPY input file=\root\level1\level2-ABC\2C.013000000B.dat output file=c:\local\project1\data\2C.013000000B.dat.ext
    06:40:37   TestModule - [INFO]result success !! ftp_site=ftp.test.com file_dir=CPY input file=\root\level1\level2-ABC\20100722B.TXT output file=c:\local\project1\data\20100722B.TXT.ext
    06:40:39   TestModule - [INFO]result success !! ftp_site=ftp.test.com file_dir=CPY input file=\root\level1\level2-DEF\20100722D1-XYZ.TXT output file=c:\local\project1\data\20100722D1-YFP.TXT.ext
    06:40:42   TestModule - [INFO]result success !! ftp_site=ftp.test.com file_dir=CPY input file=\root\level1\level2-DEF\2C.250B output file=c:\local\project1\data\2C.250B.ext
    

    BR

    爱德华

6 个答案:

答案 0 :(得分:2)

使用拆分是一个好主意。如果你真的想要一个正则表达式,我会这样做:

(\d\d:\d\d:\d\d).*?input file=.*?(ABC|DEF)\\\\(.*?)\soutput

测试here

答案 1 :(得分:2)

正则表达式非常擅长解决像这样的问题 - 即解析日志文件记录。 MarcoS的答案很好地解决了你的问题。但是,另一种方法是编写一个(可重用的)通用函数,该函数将日志文件记录分解为其各种组件,并返回包含所有这些已解析组件的匹配对象。分解后,可以轻松地将测试应用于组件部分以检查各种要求(例如输入文件路径必须以ABCDEF结尾)。这是一个python脚本,它具有这样一个功能:decomposeLogEntry()并演示如何使用它来解决手头的问题:

import re
def decomposeLogEntry(text):
    r""" Decompose log file entry into its various components.

    If text is a valid log entry, return regex match object of
    log entry components strings. Otherwise return None."""
    return re.match(r"""
        # Decompose log file entry into its various components.
        ^                            # Anchor to start of string
        (?P<time>\d\d:\d\d:\d\d)     # Capture: time
        \s+
        (?P<modname>\w+?)            # Capture module name
        \s-\s\[
        (?P<msgtype>[^]]+)           # Capture message type
        \]
        (?P<message>[^!]+)           # Capture message text
        !!\sftp_site=
        (?P<ftpsite>\S+?)            # Capture ftp URL
        \sfile_dir=
        (?P<filedir>\S+?)            # Capture file directory?
        \sinput\sfile=
        (?P<infile>                  # Capture input path and filename
          (?P<infilepath>\S+)\\      # Capture input file path
          (?P<infilename>[^\s\\]+)   # Capture input file filename
        )
        \soutput\sfile=
        (?P<outfile>                 # Capture input path and filename
          (?P<outfilepath>\S+)\\     # Capture output file path
          (?P<outfilename>[^\s\\]+)  # Capture output file filename
        )
        \s*                          # Optional whitespace at end.
        $                            # Anchor to end of string
        """, text, re.IGNORECASE | re.VERBOSE)

# Demonstrate decomposeLogEntry function. Print components of all log entries.
f=open("testdata.log")
mcnt = 0
for line in f:
    # Decompose this line into its components.
    m = decomposeLogEntry(line)
    if m:
        mcnt += 1
        print "Match number %d" % (mcnt)
        print "  Time:             %s" % m.group("time")
        print "  Module name:      %s" % m.group("modname")
        print "  Message type:     %s" % m.group("time")
        print "  Message:          %s" % m.group("message")
        print "  FTP site URL:     %s" % m.group("ftpsite")
        print "  Input file:       %s" % m.group("infile")
        print "  Input file path:  %s" % m.group("infilepath")
        print "  Input file name:  %s" % m.group("infilename")
        print "  Output file:      %s" % m.group("outfile")
        print "  Output file path: %s" % m.group("outfilepath")
        print "  Output file name: %s" % m.group("outfilename")
        print "\n",
f.close()

# Next pick out only the desired data.
f=open("testdata.log")
mcnt = 0
matches = []
for line in f:
    # Decompose this line into its components.
    m = decomposeLogEntry(line)
    if m:
        # See if this record meets desired requirements
        if re.search(r"ABC$|DEF$", m.group("infilepath")):
            matches.append(line)
f.close()
print "There were %d matching records" % len(matches)

此功能不仅可以选择您感兴趣的各个部分,还可以验证输入并拒绝格式错误的记录。编写和调试后,其他需要分析日志文件以满足其他要求的程序可以重用此函数。

以下是应用于测试数据时脚本的输出:

r"""
Match number 1
  Time:             08:38:36
  Module name:      TestModule
  Message type:     08:38:36
  Message:          result success
  FTP site URL:     ftp.test.com
  Input file:       \root\level1\level2-ABC\2C.013000000B.dat
  Input file path:  \root\level1\level2-ABC
  Input file name:  2C.013000000B.dat
  Output file:      c:\local\project1\data\2C.013000000B.dat.ext
  Output file path: c:\local\project1\data
  Output file name: 2C.013000000B.dat.ext

Match number 2
  Time:             06:40:37
  Module name:      TestModule
  Message type:     06:40:37
  Message:          result success
  FTP site URL:     ftp.test.com
  Input file:       \root\level1\level2-ABC\20100722B.TXT
  Input file path:  \root\level1\level2-ABC
  Input file name:  20100722B.TXT
  Output file:      c:\local\project1\data\20100722B.TXT.ext
  Output file path: c:\local\project1\data
  Output file name: 20100722B.TXT.ext

Match number 3
  Time:             06:40:39
  Module name:      TestModule
  Message type:     06:40:39
  Message:          result success
  FTP site URL:     ftp.test.com
  Input file:       \root\level1\level2-DEF\20100722D1-XYZ.TXT
  Input file path:  \root\level1\level2-DEF
  Input file name:  20100722D1-XYZ.TXT
  Output file:      c:\local\project1\data\20100722D1-YFP.TXT.ext
  Output file path: c:\local\project1\data
  Output file name: 20100722D1-YFP.TXT.ext

Match number 4
  Time:             06:40:42
  Module name:      TestModule
  Message type:     06:40:42
  Message:          result success
  FTP site URL:     ftp.test.com
  Input file:       \root\level1\level2-DEF\2C.250B
  Input file path:  \root\level1\level2-DEF
  Input file name:  2C.250B
  Output file:      c:\local\project1\data\2C.250B.ext
  Output file path: c:\local\project1\data
  Output file name: 2C.250B.ext

There were 4 matching records
"""

答案 2 :(得分:1)

如果您使用正则表达式工具,它将使您的生活更容易进行故障排除正则表达式。试试this free one - 可能有更好的,但效果很好。您可以将日志文件粘贴到那里,并一次尝试一下你的正则表达式,它会实时突出显示匹配。

答案 3 :(得分:1)

为何选择正则表达式?

考虑使用split来获取所有单词。这将直接为您提供时间戳。然后浏览所有其他单词,检查其中是否有=,在这种情况下再次拆分它们,并且您可以很好地获得路径和其他参数。标准Python路径处理(os.path)将帮助您获取文件夹和文件名。

当然,如果您的路径名可能包含空格,则此方法会失败,但除此之外绝对值得考虑。

答案 4 :(得分:1)

您可以通过正常的字符串处理

来完成
f=open("file")
for line in f:
    date,b = line.split("input")
    print "time: " , date.split()[0]
    input_path = b.split("output")[0]
    tokens=input_path.split("\\")
    filename=tokens[-1]
    directory=tokens[-2].split("-")[-1]
    print filename, directory
f.close()

答案 5 :(得分:0)

这适用于您的示例:

r'(\d\d:\d\d:\d\d).*(ABC|DEF).*?([^\\]*)\soutput.*'

虽然这里有一个写得很好的正则表达式,但我会以不同的方式处理这个问题。最具体地说,os.path.split旨在将文件名与基本路径分开,并处理此正则表达式忽略的所有极端情况。