我是Python3的新手,正在使用文本文件。我试图从以JavaScript(.js)扩展名结尾的日志文件中提取所有文件名。该文件还包含其他文件扩展名。我只想返回文件名而不返回路径,按字母顺序对输出进行排序,并显示uniuqe值,因为日志条目中有重复项。
日志文件中的示例为:
72.133.47.242--[25 / Apr / 2013:15:45:28 -0700]“ GET /include/jquery.js HTTP / 1.1” 200 25139
22.133.47.242--[25 / Apr / 2013:15:45:28 -0700]“ GET /include/jquery.jshowoff.js HTTP / 1.1” 200 25139
在这种情况下,我只想返回jquery.js和jquery.jshowoff.js,而不是HTTP请求和其他日志数据。
到目前为止,这是我的代码:
filepath = '/home/user/Documents/access_log.txt'
with open(filepath, 'r') as access_log:
contents = access_log.readlines()
for line in contents:
if ".js" in line:
print(line)
我的输出只返回其中包含。js的行,但我不知道如何提取其余部分。我尝试使用正则表达式进行匹配,但是由于使用它也是新手,因此并未成功。任何帮助将不胜感激。
这是另一个纯Python解决方案,使用以下logfile.txt
作为输入:
72.133.47.242 - - [25/Apr/2013:15:45:28 -0700] "GET /include/jquery.js HTTP/1.1" 200 25139
22.133.47.242 - - [25/Apr/2013:15:45:28 -0700] "GET /include/jquery.jshowoff.js HTTP/1.1" 200 25139
72.133.47.242 - - [25/Apr/2013:15:45:28 -0700] "GET /2468.js HTTP/1.1" 200 25139
72.133.47.242 - - [25/Apr/2013:15:45:28 -0700] "GET /Abcd.js HTTP/1.1" 200 25139
22.133.47.242 - - [25/Apr/2013:15:45:28 -0700] "GET /abcd.js HTTP/1.1" 200 25139
72.133.47.242 - - [25/Apr/2013:15:45:28 -0700] "GET /aBcd.js HTTP/1.1" 200 25139
22.133.47.242 - - [25/Apr/2013:15:45:28 -0700] "GET / asd.js HTTP/1.1" 200 25139
72.133.47.242 - - [25/Apr/2013:15:45:28 -0700] "GET /include/index.html HTTP/1.1" 200 25139
72.133.47.242 - - [25/Apr/2013:15:45:28 -0700] "GET /include/login.jsp HTTP/1.1" 200 25139
所有JavaScript文件名都存储在set
中,因为您只需要唯一的值。在打印之前,它们会按字母顺序排序。
迭代每一行,从字符串末尾开始查找第一个.js
的索引,然后从找到/
的地方开始查找第一个.js
的索引,向左移动。
使用这两个索引对行进行切片以提供文件名。如果未找到.js
,则rfind
返回-1
,这没关系,因为我们在将文件名添加到.js
之前检查文件名是否以set
结尾。您可以使用rindex
,但是对于没有ValueError
的行,则需要处理.js
。
filenames = set()
with open(r"C:\Users\Old Joe\Desktop\logfile.txt") as f:
for line in f:
end = line.rfind(".js") + 3 # 3 = len(".js")
start = line.rfind("/", 0, end) + 1 # 1 = len("/")
filename = line[start:end]
if filename.endswith(".js"):
filenames.add(filename)
for filename in sorted(filenames, key=str.lower):
print(filename)
输出:
asd.js
2468.js
aBcd.js
abcd.js
Abcd.js
jquery.js
jquery.jshowoff.js
login.js
这可以用正则表达式来完成,但是我想我只给出一个python解决方案。
我采用的方法是根据OS路径字符/
分割每一行。对于Windows操作系统,它将为'\'(因此,如果您希望它是跨平台的,请记住这一点)。这给出了一个列表。然后,我们在列表中的每个元素中搜索“ .js”。该空间应始终存在。带有文件名的元素将在文件名后面有多余的内容,因此仅在“ .js”上分割,并仅保留该分割的第一个元素。我也在代码中注释了这些片段。
with open(filepath, 'r') as access_log:
contents = access_log.readlines()
log_filenames = []
for line in contents:
# log_filenames on mac/linux will use / so split on that then search for filename
for fragment in line.split('/'):
if ".js " in fragment:
# there will be text after .js, so remove it
frags = fragment.split('.js ')
# split on ".js " will give us the base filename as first element of list
basename = frags[0]
filename = basename + '.js'
log_filenames.append(filename)
# get unique values
log_filenames = list(set(log_filenames))
# sort
log_filenames.sort()
print('\n'.join(log_filenames))
输出:
jquery.js
jquery.jshowoff.js
注意:在获取唯一值时,我将set
转换回了list
,以防万一您不习惯使用set
。