递归练习题-doc文件目录解析-Python语言实现

目录

解决思路:

解决过程:

结果输出示例:

附加问题:如果我们需要更多的目录状态信息呢?

完整代码及示例文件获取:


最近接触一些超大word文档,其目录就有五六页,但发现目录使用标准格式,就想开发一个目录解析工具,用于查看每个目录级中包含多少最小子目录。
目录示例如下(最后的数字是页码):
4.1 数学习题      14
4.1.1 选择题      14
4.1.1.1 矩阵分析      14
4.1.1.1.1 矩阵分析习题1      14
4.1.1.1.2 矩阵分析习题2      15
4.1.1.2 微积分      16
4.1.1.2.1 微积分习题1 [已完成]      16
4.1.1.2.2 微积分习题2 [已完成]      16
4.1.1.2.3 微积分习题3 [已完成]      17
4.1.1.2.4 微积分习题4      17
4.1.1.3 概率论      18
4.1.1.3.1 概率论习题1      18
4.1.2 填空题      19
4.1.2.1 矩阵分析      19
4.1.2.1.1 矩阵分析练习题1      19
4.2 英语
4.2.1 历年真题      19
4.2.1.1 完形填空      19
4.2.1.1.1 完形填空2016年真题      19
4.2.1.1.2 完形填空2017年真题 [已完成]      19
4.2.1.1.3 完形填空2018年真题 [已完成]      19
4.2.1.2 阅读理解      19
4.2.1.2.1 阅读理解2016年真题 [已完成]      19
4.2.1.2.2 阅读理解2017年真题 [已完成]      19
4.2.1.2.3 阅读理解2018年真题 [已完成]      19
可以看出,上面这个示例,最小子目录是5级目录,则按照我们的要求规则,输出统计为
4.1 数学习题      8
4.1.1 选择题      7
4.1.1.1 矩阵分析      2

解决思路:

1、构建合适的数据结构,用于存储各个目录的存储信息;
2、目录层级(深度)获取,用于知晓当前目录属于哪一级别;
3、使用递归完成目录数据结构构建;
4、使用递归完成目录数据结构输出;

解决过程:


可以看出,我们这个习题最难的地方在于 
3、使用递归完成目录数据结构构建;
首先,我们先解决几个简单的问题:
1、构建合适的数据结构,用于存储各个目录的存储信息;
这里我考虑使用Python的字典内置类型,经过大量反复测试后,发现此种结构比较适合:
{'this_content': this_line, 'sub_content_lst': [], 'count': 0}
'this_content' 字段用于保存当前行信息,便于输出;
'sub_content_lst' 字段用于保存当前目录行的子目录,为列表类型,保存的内容为下一层目录,字典类型,即当前字典结构(如果当前为最底层目录则为空)
'count' 字段为数字类型,用于保存当前目录行包含最底层子目录个数(注意最底层目录与下一层目录的区别)

2、目录层级(深度)获取,用于知晓当前目录属于哪一级别;
这个比较简单,使用正则匹配即可:

def find_content_deep(line):
    pat_deep_1 = r'^\d+ '
    pat_deep_2 = r'^\d+\.\d+ '
    pat_deep_3 = r'^\d+\.\d+.\d+ '
    pat_deep_4 = r'^\d+\.\d+.\d+.\d+ '
    pat_deep_5 = r'^\d+\.\d+.\d+.\d+.\d+ '
    pat_lst = [pat_deep_1, pat_deep_2, pat_deep_3, pat_deep_4, pat_deep_5]
    for index, pat_deep in enumerate(pat_lst):
        if re.search(pat_deep, line):
            return index + 1
    raise Exception('未知的目录标题参数')
当然,你也可以根据自己的目录格式进行正则匹配;

3、使用递归完成目录数据结构构建;
这里我不直接给出答案,如果大家有兴趣可以自己试试看,我会给出自己解决的编写步骤;

这是我能运行的第一个(保留)版本:

def iter_calc(this_line, f, clac_max_deep):
    # this_line = f.readline().strip().split('\t')[0]
    # 获取当前目录行深度
    cur_deep = find_content_deep(this_line)
    # 构造当前行目录结构
    cur_content_info_dct = {'this_content': this_line, 'sub_content_lst': [], 'count': 0}
    # 如果为最大深度则个数赋值为1,并返回
    if cur_deep == clac_max_deep:
        cur_content_info_dct['count'] = 1
        return cur_content_info_dct, None
    while True:
        next_line = f.readline().strip().split('\t')[0]
        next_deep = find_content_deep(next_line)
        if cur_deep < next_deep:
            sub_content_info_dct, return_line = iter_calc(next_line, f, clac_max_deep)
            if return_line is None:
                cur_content_info_dct['sub_content_lst'].append(sub_content_info_dct)
                cur_content_info_dct['count'] += sub_content_info_dct['count']
            else:
                cur_content_info_dct['sub_content_lst'].append(sub_content_info_dct)
                cur_content_info_dct['count'] += sub_content_info_dct['count']
                return sub_content_info_dct, return_line
        elif cur_deep == next_deep:
            return cur_content_info_dct, next_line
        elif cur_deep > next_deep:
            return cur_content_info_dct, next_line
这个版本问题在于,只能实现单层递归,非最底层只能保留一个……

下面这个是我第二个保留运行版本,问题在于递归不完全:
def iter_calc_2(this_line, f, clac_max_deep):
    cur_deep = find_content_deep(this_line)
    cur_content_info_dct = {'this_content': this_line, 'sub_content_lst': [], 'count': 0}
    next_line = f.readline().strip().split('\t')[0]
    next_deep = find_content_deep(next_line)
    while True:
        if cur_deep == clac_max_deep:
            cur_content_info_dct['count'] = 1
            return cur_content_info_dct, next_line
        elif cur_deep >= next_deep:
            return cur_content_info_dct, next_line
        elif cur_deep < next_deep:
            sub_content_info_dct, next_line = iter_calc_2(next_line, f, clac_max_deep)
            next_deep = find_content_deep(next_line)
            cur_content_info_dct['sub_content_lst'].append(sub_content_info_dct)
            cur_content_info_dct['count'] += sub_content_info_dct['count']
            print(cur_content_info_dct)
下面是能够实现功能的版本,但写的太杂糅了:


def iter_calc_3(this_line, f, clac_max_deep):
    cur_deep = find_content_deep(this_line)
    cur_content_info_dct = {"this_content": this_line, "sub_content_lst": [], "count": 0}
    next_line = f.readline()
    if next_line:
        next_line = next_line.strip().split('\t')[0]
        next_deep = find_content_deep(next_line)
    else:
        if cur_deep == clac_max_deep:
            cur_content_info_dct['count'] = 1
            return cur_content_info_dct, next_line
        else:
            return cur_content_info_dct, next_line
    while True:
        if cur_deep == clac_max_deep:
            cur_content_info_dct['count'] = 1
            return cur_content_info_dct, next_line
        elif cur_deep >= next_deep:
            return cur_content_info_dct, next_line
        elif cur_deep < next_deep:
            sub_content_info_dct, next_line = iter_calc_3(next_line, f, clac_max_deep)
            if not next_line:
                cur_content_info_dct['sub_content_lst'].append(sub_content_info_dct)
                cur_content_info_dct['count'] += sub_content_info_dct['count']
                return cur_content_info_dct, next_line
            next_deep = find_content_deep(next_line)
            cur_content_info_dct['sub_content_lst'].append(sub_content_info_dct)
            cur_content_info_dct['count'] += sub_content_info_dct['count']
            # print(cur_content_info_dct)
好吧,经过美化得到一个优化版本:



def iter_calc_4(this_line, f, clac_max_deep):
    # 获取当前目录行深度
    cur_deep = find_content_deep(this_line)
    # 构建当前目录行数据结构
    cur_content_info_dct = {"this_content": this_line, "sub_content_lst": [], "count": 0}
    # 读取下一行目录信息
    next_line = f.readline()
    # 判断是否为空,并去除页码,获取深度信息
    if next_line:
        next_line = next_line.strip().split('\t')[0]
        next_deep = find_content_deep(next_line)
    else:
        # 如果为最大深度,则返回
        if cur_deep == clac_max_deep:
            cur_content_info_dct['count'] = 1
            return cur_content_info_dct, next_line
        else:
            return cur_content_info_dct, next_line
    while True:
        # 如果下一行目录为上一级或同级,则直接返回
        if cur_deep >= next_deep:
            return cur_content_info_dct, next_line
        # 如果下一行目录为下一级,则进行数据统计,填充 "sub_content_lst" 字段并继续递归
        elif cur_deep < next_deep:
            sub_content_info_dct, next_line = iter_calc_4(next_line, f, clac_max_deep)
            cur_content_info_dct['sub_content_lst'].append(sub_content_info_dct)
            cur_content_info_dct['count'] += sub_content_info_dct['count']
            # 注意这里 next_line 是递归新产生的,需要判断是否为空
            if not next_line:
                return cur_content_info_dct, next_line
            next_deep = find_content_deep(next_line)
            # print(cur_content_info_dct)
需要注意的是,到目前为止,我们还没有对超级层(即目录最高层也组成一个列表类型)的处理,为了统一结构,我们仍然用递归中的数据类型,但我们手工完成字段内容:


def anaylse_doc_content_2():
    p_input_content = './content_file.txt'
    p_output_content = './output_content_file.txt'
    clac_max_deep = 5   # 指定统计目录的最大深度
    super_content_info_dct = {"this_content": '[content]', "sub_content_lst": [], "count": 0}
    with open(p_input_content, encoding='utf-8') as f:
        # cur_content_info_dct = {"this_content": this_line, "sub_content_lst": [], "count": 0}
        next_line = f.readline()
        if next_line:
            next_line = next_line.strip().split('\t')[0]
        else:
            raise Exception('空目录')
        while True:
            sub_content_info_dct, next_line = iter_calc_4(next_line, f, clac_max_deep)
            super_content_info_dct['sub_content_lst'].append(sub_content_info_dct)
            super_content_info_dct['count'] += sub_content_info_dct['count']
            if not next_line:
                break
    print(super_content_info_dct)
    super_content_info_json= json.dumps(super_content_info_dct, ensure_ascii=False)
    print(super_content_info_json)
    pass



if __name__ == '__main__':
    anaylse_doc_content_2()
    print('all done, weiran 2019年2月10日')

结果输出示例:

{'this_content': '[content]', 'sub_content_lst': [{'this_content': '4.1 数学习题 \xa0 \xa0 \xa014', 'sub_content_lst': [{'this_content': '4.1.1 选择题 \xa0 \xa0 \xa014', 'sub_content_lst': [{'this_content': '4.1.1.1 矩阵分析 \xa0 \xa0 \xa014', 'sub_content_lst': [{'this_content': '4.1.1.1.1 矩阵分析习题1 \xa0 \xa0 \xa014', 'sub_content_lst': [], 'count': 1}, {'this_content': '4.1.1.1.2 矩阵分析习题2 \xa0 \xa0 \xa015', 'sub_content_lst': [], 'count': 1}], 'count': 2}, {'this_content': '4.1.1.2 微积分 \xa0 \xa0 \xa016', 'sub_content_lst': [{'this_content': '4.1.1.2.1 微积分习题1 [已完成] \xa0 \xa0 \xa016', 'sub_content_lst': [], 'count': 1}, {'this_content': '4.1.1.2.2 微积分习题2 [已完成] \xa0 \xa0 \xa016', 'sub_content_lst': [], 'count': 1}, {'this_content': '4.1.1.2.3 微积分习题3 [已完成] \xa0 \xa0 \xa017', 'sub_content_lst': [], 'count': 1}, {'this_content': '4.1.1.2.4 微积分习题4 \xa0 \xa0 \xa017', 'sub_content_lst': [], 'count': 1}], 'count': 4}, {'this_content': '4.1.1.3 概率论 \xa0 \xa0 \xa018', 'sub_content_lst': [{'this_content': '4.1.1.3.1 概率论习题1 \xa0 \xa0 \xa018', 'sub_content_lst': [], 'count': 1}], 'count': 1}], 'count': 7}, {'this_content': '4.1.2 填空题 \xa0 \xa0 \xa019', 'sub_content_lst': [{'this_content': '4.1.2.1 矩阵分析 \xa0 \xa0 \xa019', 'sub_content_lst': [{'this_content': '4.1.2.1.1 矩阵分析练习题1 \xa0 \xa0 \xa019', 'sub_content_lst': [], 'count': 1}], 'count': 1}], 'count': 1}], 'count': 8}, {'this_content': '4.2 英语', 'sub_content_lst': [{'this_content': '4.2.1 历年真题 \xa0 \xa0 \xa019', 'sub_content_lst': [{'this_content': '4.2.1.1 完形填空 \xa0 \xa0 \xa019', 'sub_content_lst': [{'this_content': '4.2.1.1.1 完形填空2016年真题 \xa0 \xa0 \xa019', 'sub_content_lst': [], 'count': 1}, {'this_content': '4.2.1.1.2 完形填空2017年真题 [已完成] \xa0 \xa0 \xa019', 'sub_content_lst': [], 'count': 1}, {'this_content': '4.2.1.1.3 完形填空2018年真题 [已完成] \xa0 \xa0 \xa019', 'sub_content_lst': [], 'count': 1}], 'count': 3}, {'this_content': '4.2.1.2 阅读理解 \xa0 \xa0 \xa019', 'sub_content_lst': [{'this_content': '4.2.1.2.1 阅读理解2016年真题 [已完成] \xa0 \xa0 \xa019', 'sub_content_lst': [], 'count': 1}, {'this_content': '4.2.1.2.2 阅读理解2017年真题 [已完成] \xa0 \xa0 \xa019', 'sub_content_lst': [], 'count': 1}, {'this_content': '4.2.1.2.3 阅读理解2018年真题 [已完成] \xa0 \xa0 \xa019', 'sub_content_lst': [], 'count': 1}], 'count': 3}], 'count': 6}], 'count': 6}], 'count': 14}
{"this_content": "[content]", "sub_content_lst": [{"this_content": "4.1 数学习题      14", "sub_content_lst": [{"this_content": "4.1.1 选择题      14", "sub_content_lst": [{"this_content": "4.1.1.1 矩阵分析      14", "sub_content_lst": [{"this_content": "4.1.1.1.1 矩阵分析习题1      14", "sub_content_lst": [], "count": 1}, {"this_content": "4.1.1.1.2 矩阵分析习题2      15", "sub_content_lst": [], "count": 1}], "count": 2}, {"this_content": "4.1.1.2 微积分      16", "sub_content_lst": [{"this_content": "4.1.1.2.1 微积分习题1 [已完成]      16", "sub_content_lst": [], "count": 1}, {"this_content": "4.1.1.2.2 微积分习题2 [已完成]      16", "sub_content_lst": [], "count": 1}, {"this_content": "4.1.1.2.3 微积分习题3 [已完成]      17", "sub_content_lst": [], "count": 1}, {"this_content": "4.1.1.2.4 微积分习题4      17", "sub_content_lst": [], "count": 1}], "count": 4}, {"this_content": "4.1.1.3 概率论      18", "sub_content_lst": [{"this_content": "4.1.1.3.1 概率论习题1      18", "sub_content_lst": [], "count": 1}], "count": 1}], "count": 7}, {"this_content": "4.1.2 填空题      19", "sub_content_lst": [{"this_content": "4.1.2.1 矩阵分析      19", "sub_content_lst": [{"this_content": "4.1.2.1.1 矩阵分析练习题1      19", "sub_content_lst": [], "count": 1}], "count": 1}], "count": 1}], "count": 8}, {"this_content": "4.2 英语", "sub_content_lst": [{"this_content": "4.2.1 历年真题      19", "sub_content_lst": [{"this_content": "4.2.1.1 完形填空      19", "sub_content_lst": [{"this_content": "4.2.1.1.1 完形填空2016年真题      19", "sub_content_lst": [], "count": 1}, {"this_content": "4.2.1.1.2 完形填空2017年真题 [已完成]      19", "sub_content_lst": [], "count": 1}, {"this_content": "4.2.1.1.3 完形填空2018年真题 [已完成]      19", "sub_content_lst": [], "count": 1}], "count": 3}, {"this_content": "4.2.1.2 阅读理解      19", "sub_content_lst": [{"this_content": "4.2.1.2.1 阅读理解2016年真题 [已完成]      19", "sub_content_lst": [], "count": 1}, {"this_content": "4.2.1.2.2 阅读理解2017年真题 [已完成]      19", "sub_content_lst": [], "count": 1}, {"this_content": "4.2.1.2.3 阅读理解2018年真题 [已完成]      19", "sub_content_lst": [], "count": 1}], "count": 3}], "count": 6}], "count": 6}], "count": 14}
all done, weiran 2019年2月10日

Process finished with exit code 0
通过json解析工具我们也可以观察输出结果符合我们的需求:


{
	"this_content": "[content]",
	"sub_content_lst": [{
		"this_content": "4.1 数学习题",
		"sub_content_lst": [{
			"this_content": "4.1.1 选择题",
			"sub_content_lst": [{
				"this_content": "4.1.1.1 矩阵分析",
				"sub_content_lst": [{
					"this_content": "4.1.1.1.1 矩阵分析习题1",
					"sub_content_lst": [],
					"count": 1
				}, {
					"this_content": "4.1.1.1.2 矩阵分析习题2",
					"sub_content_lst": [],
					"count": 1
				}],
				"count": 2
			}, {
				"this_content": "4.1.1.2 微积分",
				"sub_content_lst": [{
					"this_content": "4.1.1.2.1 微积分习题1 [已完成]",
					"sub_content_lst": [],
					"count": 1
				}, {
					"this_content": "4.1.1.2.2 微积分习题2 [已完成]",
					"sub_content_lst": [],
					"count": 1
				}, {
					"this_content": "4.1.1.2.3 微积分习题3 [已完成]",
					"sub_content_lst": [],
					"count": 1
				}, {
					"this_content": "4.1.1.2.4 微积分习题4",
					"sub_content_lst": [],
					"count": 1
				}],
				"count": 4
			}, {
				"this_content": "4.1.1.3 概率论",
				"sub_content_lst": [{
					"this_content": "4.1.1.3.1 概率论习题1",
					"sub_content_lst": [],
					"count": 1
				}],
				"count": 1
			}],
			"count": 7
		}, {
			"this_content": "4.1.2 填空题",
			"sub_content_lst": [{
				"this_content": "4.1.2.1 矩阵分析",
				"sub_content_lst": [{
					"this_content": "4.1.2.1.1 矩阵分析练习题1",
					"sub_content_lst": [],
					"count": 1
				}],
				"count": 1
			}],
			"count": 1
		}],
		"count": 8
	}, {
		"this_content": "4.2 英语",
		"sub_content_lst": [{
			"this_content": "4.2.1 历年真题",
			"sub_content_lst": [{
				"this_content": "4.2.1.1 完形填空",
				"sub_content_lst": [{
					"this_content": "4.2.1.1.1 完形填空2016年真题",
					"sub_content_lst": [],
					"count": 1
				}, {
					"this_content": "4.2.1.1.2 完形填空2017年真题 [已完成]",
					"sub_content_lst": [],
					"count": 1
				}, {
					"this_content": "4.2.1.1.3 完形填空2018年真题 [已完成]",
					"sub_content_lst": [],
					"count": 1
				}],
				"count": 3
			}, {
				"this_content": "4.2.1.2 阅读理解",
				"sub_content_lst": [{
					"this_content": "4.2.1.2.1 阅读理解2016年真题 [已完成]",
					"sub_content_lst": [],
					"count": 1
				}, {
					"this_content": "4.2.1.2.2 阅读理解2017年真题 [已完成]",
					"sub_content_lst": [],
					"count": 1
				}, {
					"this_content": "4.2.1.2.3 阅读理解2018年真题 [已完成]",
					"sub_content_lst": [],
					"count": 1
				}],
				"count": 3
			}],
			"count": 6
		}],
		"count": 6
	}],
	"count": 14
}
好了,最后只剩下一个输出递归,实现相当简单:

4、使用递归完成目录数据结构输出;

def anaylse_doc_content_2():
    p_input_content = './content_file.txt'
    p_output_content = './output_content_file.txt'
    clac_max_deep = 5   # 指定统计目录的最大深度
    super_content_info_dct = {"this_content": '[content]', "sub_content_lst": [], "count": 0}
    with open(p_input_content, encoding='utf-8') as f:
        # cur_content_info_dct = {"this_content": this_line, "sub_content_lst": [], "count": 0}
        next_line = f.readline()
        if next_line:
            next_line = next_line.strip().split('      ')[0]
        else:
            raise Exception('空目录')
        while True:
            sub_content_info_dct, next_line = iter_calc_4(next_line, f, clac_max_deep)
            super_content_info_dct['sub_content_lst'].append(sub_content_info_dct)
            super_content_info_dct['count'] += sub_content_info_dct['count']
            if not next_line:
                break
    print(super_content_info_dct)
    super_content_info_json= json.dumps(super_content_info_dct, ensure_ascii=False)
    print(super_content_info_json)
    with open(p_output_content, 'w', encoding='utf-8') as f_output:
        formatting_output_content(super_content_info_dct, f_output)
    pass


# cur_content_info_dct = {'this_content': this_line, 'sub_content_lst': [], 'count': 0}
def formatting_output_content(dct_content, f_output):
    print('-' * 50)
    # print(dct_content)
    # print(dct_content['this_content'])
    # print(dct_content['count'])
    f_output.write(f"{dct_content['this_content']} :: {dct_content['count']}\n")
    for sub_dct in dct_content['sub_content_lst']:
        formatting_output_content(sub_dct, f_output)


if __name__ == '__main__':
    anaylse_doc_content_2()
    print('all done, weiran 2019年2月10日')
那么,输出结果为:
[content] :: 14
4.1 数学习题 :: 8
4.1.1 选择题 :: 7
4.1.1.1 矩阵分析 :: 2
4.1.1.1.1 矩阵分析习题1 :: 1
4.1.1.1.2 矩阵分析习题2 :: 1
4.1.1.2 微积分 :: 4
4.1.1.2.1 微积分习题1 [已完成] :: 1
4.1.1.2.2 微积分习题2 [已完成] :: 1
4.1.1.2.3 微积分习题3 [已完成] :: 1
4.1.1.2.4 微积分习题4 :: 1
4.1.1.3 概率论 :: 1
4.1.1.3.1 概率论习题1 :: 1
4.1.2 填空题 :: 1
4.1.2.1 矩阵分析 :: 1
4.1.2.1.1 矩阵分析练习题1 :: 1
4.2 英语 :: 6
4.2.1 历年真题 :: 6
4.2.1.1 完形填空 :: 3
4.2.1.1.1 完形填空2016年真题 :: 1
4.2.1.1.2 完形填空2017年真题 [已完成] :: 1
4.2.1.1.3 完形填空2018年真题 [已完成] :: 1
4.2.1.2 阅读理解 :: 3
4.2.1.2.1 阅读理解2016年真题 [已完成] :: 1
4.2.1.2.2 阅读理解2017年真题 [已完成] :: 1
4.2.1.2.3 阅读理解2018年真题 [已完成] :: 1
满足我们的要求哈!

附加问题:如果我们需要更多的目录状态信息呢?

如,在上面的目录中,我特意的增加  [已完成] ,即不仅要输出目录统计数,还要输出完成/未完成/总数的统计,如何处理呢?


其实这个问题也简单,稍微改变一下字典类型就行了(我当时花了10分钟就编写完成):
主要修改count字段,把这个属性也变成一个字典类型:代码片段为:

def iter_calc_4(this_line, f, clac_max_deep):
    cur_deep = find_content_deep(this_line)
    cur_content_info_dct = {"this_content": this_line, "sub_content_lst": [], "count_detail": {'finished_count': 0, 'unfinished_count': 0, 'all_count': 0}}
    next_line = f.readline()
    if next_line:
        # next_line = next_line.strip().split('\t')[0]
        next_line = next_line.strip().split('      ')[0]
        next_deep = find_content_deep(next_line)
    else:
        if cur_deep == clac_max_deep:
            cur_content_info_dct['count_detail']['all_count'] = 1
            if '[已完成]' in this_line:
                cur_content_info_dct['count_detail']['finished_count'] = 1
            else:
                cur_content_info_dct['count_detail']['unfinished_count'] = 1
            return cur_content_info_dct, next_line
        else:
            return cur_content_info_dct, next_line
    while True:
        if cur_deep == clac_max_deep:
            cur_content_info_dct['count_detail']['all_count'] = 1
            if '[已完成]' in this_line:
                cur_content_info_dct['count_detail']['finished_count'] = 1
            else:
                cur_content_info_dct['count_detail']['unfinished_count'] = 1
            return cur_content_info_dct, next_line
        elif cur_deep >= next_deep:
            return cur_content_info_dct, next_line
        elif cur_deep < next_deep:
            sub_content_info_dct, next_line = iter_calc_4(next_line, f, clac_max_deep)
            cur_content_info_dct['sub_content_lst'].append(sub_content_info_dct)
            cur_content_info_dct['count_detail']['all_count'] += sub_content_info_dct['count_detail']['all_count']
            cur_content_info_dct['count_detail']['finished_count'] += sub_content_info_dct['count_detail']['finished_count']
            cur_content_info_dct['count_detail']['unfinished_count'] += sub_content_info_dct['count_detail']['unfinished_count']
            if not next_line:
                return cur_content_info_dct, next_line
            next_deep = find_content_deep(next_line)
            # print(cur_content_info_dct)


# [task_study] 正则表达式处理多级目录
def anaylse_doc_content_2():
    p_input_content = './input_content.txt'    # D:\Program Files\weiran_tools\programming_python\content_anaylse\input_content.txt
    p_output_content = './output_content_file.txt'
    clac_max_deep = 5
    super_content_info_dct = {"this_content": '[content]', "sub_content_lst": [], "count_detail": {'finished_count': 0, 'unfinished_count': 0, 'all_count': 0}}
    with open(p_input_content, encoding='utf-8') as f:
        # cur_content_info_dct = {"this_content": this_line, "sub_content_lst": [], "count": 0}
        next_line = f.readline()
        if next_line:
            # next_line = next_line.strip().split('\t')[0]
            next_line = next_line.strip().split(r'      ')[0]
        else:
            raise Exception('空目录')
        while True:
            sub_content_info_dct, next_line = iter_calc_4(next_line, f, clac_max_deep)
            super_content_info_dct['sub_content_lst'].append(sub_content_info_dct)
            super_content_info_dct['count_detail']['all_count'] += sub_content_info_dct['count_detail']['all_count']
            super_content_info_dct['count_detail']['finished_count'] += sub_content_info_dct['count_detail']['finished_count']
            super_content_info_dct['count_detail']['unfinished_count'] += sub_content_info_dct['count_detail']['unfinished_count']
            if not next_line:
                break
    print(super_content_info_dct)
    super_content_info_json= json.dumps(super_content_info_dct, ensure_ascii=False)
    print(super_content_info_json)
    # f_output = open(p_output_content, 'w', encoding='UTF-8')
    f_output = open(p_output_content, 'w')
    # with open(p_output_content, 'w', encoding='utf-8') as f_output:
    formatting_output_content(super_content_info_dct, f_output)
    f_output.close()
    pass


# cur_content_info_dct = {'this_content': this_line, 'sub_content_lst': [], 'count': 0}
def formatting_output_content(dct_content, f_output):
    print('-' * 50)
    # print(dct_content)
    # print(dct_content['this_content'])
    # print(dct_content['count'])
    print(f"{dct_content['this_content']}     合计:{dct_content['count_detail']['all_count']}    已完成:{dct_content['count_detail']['finished_count']}    未完成:{dct_content['count_detail']['unfinished_count']}\n")
    f_output.write(f"{dct_content['this_content']}     合计:{dct_content['count_detail']['all_count']}    已完成:{dct_content['count_detail']['finished_count']}    未完成:{dct_content['count_detail']['unfinished_count']}\n")
    for sub_dct in dct_content['sub_content_lst']:
        formatting_output_content(sub_dct, f_output)


if __name__ == '__main__':
    anaylse_doc_content_2()
    print('all done. weiran 20190206')
最终输出结果:


[content]     合计:14    已完成:8    未完成:6
4.1 数学习题     合计:8    已完成:3    未完成:5
4.1.1 选择题     合计:7    已完成:3    未完成:4
4.1.1.1 矩阵分析     合计:2    已完成:0    未完成:2
4.1.1.1.1 矩阵分析习题1     合计:1    已完成:0    未完成:1
4.1.1.1.2 矩阵分析习题2     合计:1    已完成:0    未完成:1
4.1.1.2 微积分     合计:4    已完成:3    未完成:1
4.1.1.2.1 微积分习题1 [已完成]     合计:1    已完成:1    未完成:0
4.1.1.2.2 微积分习题2 [已完成]     合计:1    已完成:1    未完成:0
4.1.1.2.3 微积分习题3 [已完成]     合计:1    已完成:1    未完成:0
4.1.1.2.4 微积分习题4     合计:1    已完成:0    未完成:1
4.1.1.3 概率论     合计:1    已完成:0    未完成:1
4.1.1.3.1 概率论习题1     合计:1    已完成:0    未完成:1
4.1.2 填空题     合计:1    已完成:0    未完成:1
4.1.2.1 矩阵分析     合计:1    已完成:0    未完成:1
4.1.2.1.1 矩阵分析练习题1     合计:1    已完成:0    未完成:1
4.2 英语     合计:6    已完成:5    未完成:1
4.2.1 历年真题     合计:6    已完成:5    未完成:1
4.2.1.1 完形填空     合计:3    已完成:2    未完成:1
4.2.1.1.1 完形填空2016年真题     合计:1    已完成:0    未完成:1
4.2.1.1.2 完形填空2017年真题 [已完成]     合计:1    已完成:1    未完成:0
4.2.1.1.3 完形填空2018年真题 [已完成]     合计:1    已完成:1    未完成:0
4.2.1.2 阅读理解     合计:3    已完成:3    未完成:0
4.2.1.2.1 阅读理解2016年真题 [已完成]     合计:1    已完成:1    未完成:0
4.2.1.2.2 阅读理解2017年真题 [已完成]     合计:1    已完成:1    未完成:0
4.2.1.2.3 阅读理解2018年真题 [已完成]     合计:1    已完成:1    未完成:0
如果你需要使用,修改代码需要如下几点注意:

1、目录深度获取,不同的目录层级格式需要不同的正则表达式,修改
find_content_deep(line)
2、按需输出信息,需要修改目录属性字典

另外,本解答应该还有很多不完善的地方,还望大家多批评指正^^
 

完整代码及示例文件获取:

https://gitee.com/YingMingQiuYou/doc_content_analysis

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值