Регулярное выражение Python для получения имени файла в длинном пути

1

Мне нужно проанализировать некоторый файл журнала, и он выглядит ниже, я хотел бы получить 3 части данных,

  • Время
  • часть каталога, в этом случае это будет ABC и DEF во входном файле.
  • имя файла во входном файле, то есть 2C.013000000B.dat, 20100722B.TXT, 20100722D1-XYZ.TXT и 2C.250B в этом случае.

Я использую это регулярное выражение, но оно не получает третьей части.

(\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

Эдвард

Теги:
file

6 ответов

2
Лучший ответ

Регулярные выражения очень хороши при решении таких проблем, как этот, например, анализ записей в файлах журналов. Ответ MarcoS прекрасно решает вашу проблему. Однако другой подход заключается в написании обобщенной функции (многократного использования), которая разлагает запись файла журнала в ее различные компоненты и возвращает объект соответствия, содержащий все эти анализируемые компоненты. После разложения тесты могут быть легко применены к составным частям для проверки различных требований (например, путь входного файла должен заканчиваться на ABC или DEF). Вот питон script, который имеет такую ​​функцию: 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)

Эта функция не только выделяет интересующие вас детали, но также проверяет входные данные и отклоняет плохо отформатированные записи. После написания и отладки эта функция может быть повторно использована другими программами, которые должны анализировать файлы журналов для других требований.

Вот результат работы script при применении к вашим тестовым данным:

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
"""
  • 0
    Спасибо, буду иметь в виду.
2

Использование split - хорошая идея. Если вы действительно хотите регулярное выражение, я бы сделал это следующим образом:

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

Проверьте здесь

  • 0
    Я пытаюсь в моей программе, он использует Python 27, но он не работает Traceback (последний вызов был последним): файл "t.py", строка 21, в <module> S3_search1 = re.compile ('(\ d \ d: \ d \ d: \ d \ d). *? входной файл =. *? (ABC | DEF) \ (. *?) \ soutput ', re.IGNORECASE) Файл "c: \ python27 \ lib \ re.py" строка 190, при компиляции возвращает _compile (шаблон, флаги) Файл "c: \ python27 \ lib \ re.py", строка 245, ошибка _компиляции, v # неверное выражение sre_constants.error: несбалансированные скобки
  • 0
    @ user729544: извините, в python вы должны позаботиться о The Backslash Plague ... еще одна причина, почему регулярное выражение может быть не очень хорошей идеей в этом случае
Показать ещё 2 комментария
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()
  • 0
    Спасибо, это работает, но я все еще хочу знать, как завершить это с помощью регулярных выражений.
1

Почему regex?

Рассмотрите возможность использования split для получения всех слов. Это даст вам временную метку. Затем пройдите все остальные слова, проверьте, есть ли в них =, разделите их снова и в этом случае у вас есть свои пути и другие параметры. Стандартная обработка пути Python (os.path) поможет вам при получении имен папок и файлов.

Конечно, этот подход терпит неудачу, если ваши имена путей могут содержать пробелы, но в противном случае это определенно стоит рассмотреть.

  • 0
    Спасибо, я пытаюсь разбить, и это работает, но я все еще хочу знать, как это может сделать регулярное выражение.
  • 1
    Некоторые люди, столкнувшись с проблемой, думают: «Я знаю, я буду использовать регулярные выражения». Теперь у них есть две проблемы.
1

Если вы используете инструмент регулярных выражений, это облегчит вам задачу поиска и устранения неполадок regex. Попробуйте этот бесплатный - есть, вероятно, лучшие, но это отлично работает. Вы можете вставить свой файл журнала там и попробовать свое регулярное выражение за раз, и он будет выделять совпадения в режиме реального времени.

  • 0
    Спасибо, я сначала попробовал в этом экспресс-сборщике, но я получил такой результат, поэтому и спрашиваю здесь. Большое спасибо. Python 2.7.1 (r271: 86832, 27 ноября 2010, 18:30:46) [MSC v.1500 32 бит (Intel)] на win32 >>> import re >>> s1 = re.compile ('\ (\ d \ w \.? \ w * \ -? \ w *.? (P3 | TXT |)) \ s ', re.IGNORECASE) Traceback (последний вызов был последним): файл "<stdin>", строка 1, в файле <module> "c: \ python27 \ lib \ re.py", строка 190, при компиляции возвращают _compile (pattern, flags) Файл "c: \ python27 \ lib \ re.py", строка 245, в _compile ошибка, v # неверное выражение sre_constants.error: несбалансированная скобка
  • 0
    Всякий раз, когда у меня есть сложное регулярное выражение, которое не работает, я пробую это время от времени ... например, я начинаю с первой части, со временем, и как только это работает, добавляет больше и т. Д. устранить неполадки таким образом.
0

Это сработало для ваших примеров:

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

Хотя хорошо написанное регулярное выражение подходит здесь, я бы подошел к этому по-другому. В частности, os.path.split предназначен для разделения имен файлов из базовых путей и касается всех случаев, которые игнорируются этим регулярным выражением.

  • 0
    Спасибо, но это не удастся, если имя файла содержит ABC или DEF, например 20100722D1-ABC.TXT, результат будет только .TXT. (\ d \ d: \ d \ d: \ d \ d). *? входной файл =. *? (ABC | DEF) \\\ (. *?) \ soutput работает нормально. Спасибо MarcoS.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню