0
点赞
收藏
分享

微信扫一扫

【Class 38】【实例】Python 实现Linux Grep 命(二)源码实现


先把题目放出来:用Python 来实现 Linux grep 命令

grep命令分析:


  1. 输入: 无论输入字符串 还是 正则表达式都能搜索
  2. 搜索: 能够遍历目录及子目录下的所有文件 (我们此处暂时先简化为 遍历目录及子目录下的所有文本文件)
    ===> 此处需实现递归目录读取,以及 文本匹配成功后,将内容append在list中
  3. 结果: 搜索结果保存在 ./result/search_result.txt 中

第一步 生成数据文件

​​【Class 37】Python 实现Linux Grep 命(一)递归生成数据​​

第二步 代码实现

#! python3
# -*- coding: utf-8 -*-
import re, os, time, shutil


# 在当前目录生成5个目录,每个目录中有不同名字的5个文件,树状循环两次
# 内容为 this is xxx文件名 \n 生成时间为当前时间: 2019/3/4-21:52:20
def generate_file(dir_name_='.\\test_dir', file_depth=0 , dir_depth=0 , dir_cnt_=0):

# 判断目录深度
if dir_depth >= 3:
dir_depth = 0
return None
dir_depth += 1
# print(dir_name_)
# 创建第一级目录
if dir_name_=='.\\test_dir' and os.path.exists(dir_name_):
shutil.rmtree(dir_name_) # 递归删除目录
os.makedirs(dir_name_)

# 创建五个txt文件
for k in range(5):
file_name=''
file_name = "%s\\Test_File_%d.txt"%(dir_name_, file_depth + k)
# 创建5个文件
fp = open(file_name, 'w')
# 内容写入
fp.write("This is %s !\nin directory: %s\nCurrent Time is %s"%( os.path.basename(file_name),dir_name_, time.strftime('%Y/%m/%d-%H:%M:%S')))
fp.close()

# 递归调用目录
for k in range(5):
# 文件命名起点增加5
file_depth += 5
# 目录名字计数计算
dir_cnt = (dir_depth-1)*5 + dir_cnt_*5 + k if dir_depth > 1 else (dir_depth-1)*5 + k
# 递归调用
generate_file("%s\\sub_dir_%d_%d"%(dir_name_,dir_depth , dir_cnt), file_depth, dir_depth , k)


# 获得文件夹中所有的.txt 文件
def get_file_list(dir_path , txt_list=[]):
# 判断dir_path 是否合法
if not os.path.exists(dir_path):
return None
# 获取当前dir_path 下的所有文件
dir_list = os.listdir(dir_path)

if len(dir_list) >= 1:
for file_txt in dir_list:
#print("%s\\%s"%( dir_path ,file_txt))
# 如果是文件,则将txt文件文件以绝对路径的形式保存在list中
if os.path.isfile( "%s\\%s"%( dir_path ,file_txt) ):
#if ".txt" in file_txt or ".TXT" in file_txt:
if str(file_txt).endswith('.txt'):
txt_list.append( os.path.abspath( "%s\\%s"%( dir_path ,file_txt) ) )

#如果是目录
if os.path.isdir( "%s\\%s"%( dir_path ,file_txt) ):
# 递归调用,继续遍历目录
get_file_list("%s\\%s"%( dir_path ,file_txt), txt_list )

else:
print("no file in this %s"%dir_path)
return None

#print('获取文件列表:', txt_list)
return txt_list


# 传入文件路径,读取并匹配单个文件内容,判断式正则表达式 还是 单纯字符串
def get_file_matched_lines(rex_str, path):
if not os.path.isfile(path):
return "Path is not file !"

# 初始化变量用于保存所有匹配的行
match_list = []
# 创建正则表达式对象
rex_obj = re.compile(rex_str , re.VERBOSE)

# 只读形式打开文件
f_name_obj = open(path, 'r') #
# 获取到该文件所有行
f_lines = f_name_obj.readlines()
# 及时关闭文件,避免造成文件占用
f_name_obj.close()

#逐行匹配
for i in f_lines:
if rex_obj.match(i):
match_list.append( "第%d行: %s" % (f_lines.index(i) , i) )

return match_list


# 代码主体
def find_grep_str(rex_str, path='.',save_file="search_result.txt"):
# 初始化变量用于保存所有匹配的行
match_list = []
tmp = []

# 获取当前目录下的所有txt 文件路径
txt_list = get_file_list(path)

#print(txt_list)
# 读取所有文件内容,如果匹配则保存 第几行 和 行内容
for f_name in txt_list:
tmp = get_file_matched_lines(rex_str, f_name)
print(tmp)
if len(tmp) == 0:
continue

match_list.append("文件名:%s\n"%(f_name))
match_list = match_list + tmp
match_list.append("\n\n")

# 保存文件
if not os.path.exists(".\\result"):
os.makedirs(".\\result")
fp = open(".\\result\\%s"%save_file, 'w')
for i in match_list:
fp.write("%s"%i)

fp.close()


if __name__ == "__main__":
# 生成测试文件
generate_file()

# 字符串匹配
str_rex = r'This\ is\ Test'
find_grep_str(str_rex, save_file="str.txt")

# 正则表达式匹配
str_rex = r'(?=.*\d{4}).*'
find_grep_str(str_rex, save_file="rex.txt")

结果如下:

字符串匹配结果 str.txt
文件名:C:\Users\Administrator\Desktop\tmp\new\test_dir\sub_dir_1_0\sub_dir_2_5\Test_File_10.txt
第0行: This is Test_File_10.txt !

文件名:C:\Users\Administrator\Desktop\tmp\new\test_dir\sub_dir_1_0\sub_dir_2_5\Test_File_11.txt
第0行: This is Test_File_11.txt !



正则表达式匹配结果 rex.txt
文件名:C:\Users\Administrator\Desktop\tmp\new\test_dir\sub_dir_1_0\sub_dir_2_5\Test_File_10.txt
第2行: Current Time is 2019/03/05-22:04:32

文件名:C:\Users\Administrator\Desktop\tmp\new\test_dir\sub_dir_1_0\sub_dir_2_5\Test_File_11.txt
第2行: Current Time is 2019/03/05-22:04:32



举报

相关推荐

0 条评论