【复盘】文档批量切割与转换:python + pandoc + shell

背景

现有一 Markdown 文件,其中有 50 个小组块,组块之间以二级标题区分。每个二级标题下有 1 张图片,然后是文字。

以下是文档中部分内容示例:

## 1. 小明

![](小明打羽毛球的球场网址)

今天小明去打羽毛球。

## 2. 小红

![](小红逛街的商店网址)

今天小红去逛街。

现在希望:

  • 把这 50 个组块单独切割出来
  • 每个组块均转换为 doc 文件
  • 文件名为小标题名(只有中文,不含数字序号)
  • 每个小组块文件中,以小标题为内文标题(只有中文,不含数字序号)

问:

如何批量完成该工作?

任务拆分

  1. 将 1 个 md 文件批量切割 md 文件 为 50 个 md 文件
  2. 切割的同时,将小标题作为文件名取出并直接为每个组块文件命名
  3. 将 50 个 md 文件批量转换成 50 个 doc 文件

工具准备

  • python:撰写批量切割的 python 脚本
  • pandoc:用于格式转换
  • bash:通过 shell 脚本实现批量的格式转换;有可能需要用上批量重命名的命令 rename 来进行边角修改

任务 1: 批量切割文档

首先思考:

如果是手动切割,过程是怎样的?

显然我们是以二级标题为切割标志的。而二级标题的代码是 ##,会不会在文中其他地方出现呢?

进一步观察与思考会发现:切割标志其实不是 ##,而是 \n## ——也就是说,段落中或者网址中出现的 ## 都不是二级标题的代码,只有换行符 \n## 连续出现时,## 才是二级标题代码。因此我们确定了切割标志为:(字符串)\n##

python 中字符串的 str.split(sep, maxsplit) 方法可接受 2 个参数[1]

  1. 第 1 个参数 sep 表示分割标志(这里是 \n##
  2. 第 2 个参数 maxsplit 表示最多分割几次(由于是 50 份,故应该切割 49 次)

所以将读入的全文以小标题为界分割为 50 份字符串的关键代码是:

# 已将全文读入 finContent 中
sp50 = finContent.split("\n##", 49)

任务 2:批量将已切割好的字符串导出到 50 个 md 文件中,并以各小标题为各文件命名

批量导出到 50 个 md 文件中并不难,如果没有上述命名需求,那么直接一个迭代 50 次的 for 循环即可解决该问题。

问题在于:

如何取得各小标题名并为新生成的文件命名?

观察每个小组块,发现规律:

  1. 每个二级标题中都有英文句号「.」,在「.」后的部分,除去空格,即为小标题所有文字,这意味着:只要取得小标题所在行的内容,就可以用 str.split() 方法取得小标题对应文字
  2. 二级标题下即为图片代码,也就是说对这 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 来解决这个问题:

  1. 读取目录下的文件列表
  2. 对读取的每个文件名执行上述 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 库中.

参考资料

  1. Python 3.5: str.split

  2. Markdown写作进阶:Pandoc入门浅谈

  3. shell 循环文件列表取出文件名

  4. Linux批量修改文件名方法小结

    原文作者:苏尚君
    原文地址: https://www.jianshu.com/p/94eebfeff1ce
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞