0

我正在尝试从特定格式的文档中提取文件名,并将它们放入列表中。该文档包含大量信息,但我关注的行如下所示,“文件名:”始终位于行首:

File Name: C:\windows\system32\cmd.exe

我尝试了以下方法:

xmlfile = open('my_file.xml', 'r')
filetext = xmlfile.read()
file_list = []
file_list.append(re.findall(r'\bFile Name:\s+.*\\.*(?=\n)', filetext))

file_list看起来像:

[['File Name: c:\\windows\\system32\\file1.exe',
  'File Name: c:\\windows\\system32\\file2.exe',
  'File Name: c:\\windows\\system32\\file3.exe']]

我正在寻找我的输出只是:

(file1.exe, file2.exe, file3.exe)

我也尝试ntpath.basename在上面的输出上使用,但看起来它想要一个字符串作为输入,而不是一个列表。

我对 Python 和一般的脚本编写非常陌生,所以任何建议都将不胜感激。

4

4 回答 4

0

您可以使用以下正则表达式获得预期的输出:

file_list = re.findall(r'\bFile Name:\s+.*\\([^\\]*)(?=\n)', filetext)

([^\\]*)\n将在遇到最终路径分隔符后捕获除斜杠之外的所有内容,请参阅在线示例。由于findall已经返回一个列表,因此无需将返回值附加到现有列表。

于 2016-05-12T14:57:07.243 回答
0

我会对此进行一些更改,以使其更清晰地阅读和分离该过程-显然可以一步完成,但我认为您的代码以后将很难管理

import re
import os

with open('my_file.xml', 'r') as xmlfile:
    filetext = xmlfile.read()   # this way the file handle goes away - you left the file open
file_list = []
my_pattern = re.compile(r'\bFile Name:\s+.*\\.*(?=\n)')
for filename in my_pattern.findall(filetext):
    cleaned_name = filename.split(os.sep)[-1]
    file_list.append(cleaned_name)
于 2016-05-12T15:02:16.733 回答
0

您可以以更具声明性的风格来完成它。它确保了更少的错误,高内存效率。

import os.path

pat = re.compile(r'\bFile Name:\s+.*\\.*(?=\n)')
with open('my_file.xml') as f:
    ms = (pat.match(line) for line in f)
    ns = (os.path.basename(m) for m in ms)
# the iterator ns emits names such as 'foo.txt'
for n in ns:
    # do something

如果您稍微更改正则表达式,即您甚至不需要的分组os.path

于 2016-05-12T15:39:30.440 回答
0

你在正确的轨道上。basename不起作用的原因是因为re.findall()返回了一个列表,该列表正在被放入另一个列表中。这是对返回的列表进行迭代并仅使用基本文件名创建另一个列表的修复程序:

import re
import os

with open('my_file.xml', 'rU') as xmlfile:
    file_text = xmlfile.read()
    file_list = [os.path.basename(fn)
                    for fn in re.findall(r'\bFile Name:\s+.*\\.*(?=\n)', file_text)]
于 2016-05-12T15:57:07.707 回答