【复盘】文档批量切割与转换:python + pandoc +
背景
现有一 Markdown 文件,其中有 50 个小组块,组块之间以二级标题区分。每个二级标题下有 1 张图片,然后是文字。
以下是文档中部分内容示例:
## 1. 小明
![](小明打羽毛球的球场网址)
今天小明去打羽毛球。
## 2. 小红
![](小红逛街的商店网址)
今天小红去逛街。
现在希望:
- 把这 50 个组块单独切割出来
- 每个组块均转换为 doc 文件
- 文件名为小标题名(只有中文,不含数字序号)
- 每个小组块文件中,以小标题为内文标题(只有中文,不含数字序号)
问:
如何批量完成该工作?
任务拆分
- 将 1 个 md 文件批量切割 md 文件 为 50 个 md 文件
- 切割的同时,将小标题作为文件名取出并直接为每个组块文件命名
- 将 50 个 md 文件批量转换成 50 个 doc 文件
工具准备
- python:撰写批量切割的 python 脚本
- pandoc:用于格式转换
- bash:通过 shell 脚本实现批量的格式转换;有可能需要用上批量重命名的命令
rename
来进行边角修改
任务 1: 批量切割文档
首先思考:
如果是手动切割,过程是怎样的?
显然我们是以二级标题为切割标志的。而二级标题的代码是 ##
,会不会在文中其他地方出现呢?
进一步观察与思考会发现:切割标志其实不是 ##
,而是 \n##
——也就是说,段落中或者网址中出现的 ##
都不是二级标题的代码,只有换行符 \n
与 ##
连续出现时,##
才是二级标题代码。因此我们确定了切割标志为:(字符串)\n##
python 中字符串的 str.split(sep, maxsplit)
方法可接受 2 个参数[1]:
- 第 1 个参数 sep 表示分割标志(这里是
\n##
) - 第 2 个参数 maxsplit 表示最多分割几次(由于是 50 份,故应该切割 49 次)
所以将读入的全文以小标题为界分割为 50 份字符串的关键代码是:
# 已将全文读入 finContent 中
sp50 = finContent.split("\n##", 49)
任务 2:批量将已切割好的字符串导出到 50 个 md 文件中,并以各小标题为各文件命名
批量导出到 50 个 md 文件中并不难,如果没有上述命名需求,那么直接一个迭代 50 次的 for 循环即可解决该问题。
问题在于:
如何取得各小标题名并为新生成的文件命名?
观察每个小组块,发现规律:
- 每个二级标题中都有英文句号「.」,在「.」后的部分,除去空格,即为小标题所有文字,这意味着:只要取得小标题所在行的内容,就可以用
str.split()
方法取得小标题对应文字 - 二级标题下即为图片代码,也就是说对这 50 个字符串而言,每个字符串可以
\n\n![](
为分割标志,从而取得小标题所在行的内容
因此取得小标题的关键代码为:
index = ((((iStr.split("\n\n![](")[0]).split('.'))[1]).split(' '))[1]
综合前 2 项任务,该脚本代码如下(同时放在 GitHub 库中):
#coding: utf-8
originPath = "/home/sushangjun/Documents/"
srcPath = originPath + "Top50Bussiness.txt"
tarPath = originPath + "output50/"
fin = open(srcPath, 'r')
finContent = fin.read()
sp50 = finContent.split("\n##", 49)
for iStr in sp50:
index = ((((iStr.split("\n\n![](")[0]).split('.'))[1]).split(' '))[1]
fout = open(tarPath + "{}.md".format(index), 'w')
fout.write("## " + index + "\n\n![](" + (iStr.split("\n\n![]("))[1])
fout.close()
fin.close()
在命令行中执行该脚本,即可完成批量切割任务。
任务 3: 批量转换格式
这里需要使用 Pandoc[2],Debian 系 Linux 只要使用 apt-get 安装即可:
$ sudo apt-get install pandoc
完成后,输入 pandoc --version
查看是否安装成功。
若安装成功,只要下述命令,即可将 a.md
转换为 a.doc
:
$ pandoc a.md -o a.doc -c Github.css
但是这只能实现单文件的格式转换,若需要多文件的格式转换,显然需要批处理。对 *nix 稍有了解的人很容易联想到使用 bash shell 来解决这个问题:
- 读取目录下的文件列表
- 对读取的每个文件名执行上述 pandoc 命令
由于事情紧急,因此查找网络资料后,在命令行中输入下述命令,完成文件格式批量转换:[3]
注:下述操作均默认在 50 个 md 文件所在目录下进行
$ ls > aa.md
$ cat aa.md |while read line
> do
> pandoc $line -o $line.doc -c Github.css
> done
这样基本完成了批量格式转换问题。但有 1 点不美:那就是在此操作下,得到的文件后缀是 .md.doc
而非 .doc
。如何解决这个问题呢?最后我们就使用 rename
方法搭配简单的正则表达式,完成该任务:[4]
rename 's/\.md.doc/\.doc/' *
相关代码也已经写成 shell script 形式上传到 GitHub 库中.