背景
現(xiàn)有一 Markdown 文件,其中有 50 個(gè)小組塊,組塊之間以二級(jí)標(biāo)題區(qū)分。每個(gè)二級(jí)標(biāo)題下有 1 張圖片,然后是文字。
以下是文檔中部分內(nèi)容示例:
## 1. 小明
網(wǎng)址)
今天小明去打羽毛球。
## 2. 小紅
址)
今天小紅去逛街。
現(xiàn)在希望:
- 把這 50 個(gè)組塊單獨(dú)切割出來(lái)
- 每個(gè)組塊均轉(zhuǎn)換為 doc 文件
- 文件名為小標(biāo)題名(只有中文,不含數(shù)字序號(hào))
- 每個(gè)小組塊文件中,以小標(biāo)題為內(nèi)文標(biāo)題(只有中文,不含數(shù)字序號(hào))
問(wèn):
如何批量完成該工作?
任務(wù)拆分
- 將 1 個(gè) md 文件批量切割 md 文件 為 50 個(gè) md 文件
- 切割的同時(shí),將小標(biāo)題作為文件名取出并直接為每個(gè)組塊文件命名
- 將 50 個(gè) md 文件批量轉(zhuǎn)換成 50 個(gè) doc 文件
工具準(zhǔn)備
- python:撰寫批量切割的 python 腳本
- pandoc:用于格式轉(zhuǎn)換
- bash:通過(guò) shell 腳本實(shí)現(xiàn)批量的格式轉(zhuǎn)換;有可能需要用上批量重命名的命令
rename
來(lái)進(jìn)行邊角修改
任務(wù) 1: 批量切割文檔
首先思考:
如果是手動(dòng)切割,過(guò)程是怎樣的?
顯然我們是以二級(jí)標(biāo)題為切割標(biāo)志的。而二級(jí)標(biāo)題的代碼是 ##
,會(huì)不會(huì)在文中其他地方出現(xiàn)呢?
進(jìn)一步觀察與思考會(huì)發(fā)現(xiàn):切割標(biāo)志其實(shí)不是 ##
,而是 \n##
——也就是說(shuō),段落中或者網(wǎng)址中出現(xiàn)的 ##
都不是二級(jí)標(biāo)題的代碼,只有換行符 \n
與 ##
連續(xù)出現(xiàn)時(shí),##
才是二級(jí)標(biāo)題代碼。因此我們確定了切割標(biāo)志為:(字符串)\n##
python 中字符串的 str.split(sep, maxsplit)
方法可接受 2 個(gè)參數(shù)[1]:
- 第 1 個(gè)參數(shù) sep 表示分割標(biāo)志(這里是
\n##
) - 第 2 個(gè)參數(shù) maxsplit 表示最多分割幾次(由于是 50 份,故應(yīng)該切割 49 次)
所以將讀入的全文以小標(biāo)題為界分割為 50 份字符串的關(guān)鍵代碼是:
# 已將全文讀入 finContent 中
sp50 = finContent.split("\n##", 49)
任務(wù) 2:批量將已切割好的字符串導(dǎo)出到 50 個(gè) md 文件中,并以各小標(biāo)題為各文件命名
批量導(dǎo)出到 50 個(gè) md 文件中并不難,如果沒(méi)有上述命名需求,那么直接一個(gè)迭代 50 次的 for 循環(huán)即可解決該問(wèn)題。
問(wèn)題在于:
如何取得各小標(biāo)題名并為新生成的文件命名?
觀察每個(gè)小組塊,發(fā)現(xiàn)規(guī)律:
- 每個(gè)二級(jí)標(biāo)題中都有英文句號(hào)「.」,在「.」后的部分,除去空格,即為小標(biāo)題所有文字,這意味著:只要取得小標(biāo)題所在行的內(nèi)容,就可以用
str.split()
方法取得小標(biāo)題對(duì)應(yīng)文字 - 二級(jí)標(biāo)題下即為圖片代碼,也就是說(shuō)對(duì)這 50 個(gè)字符串而言,每個(gè)字符串可以
\n\n志,從而取得小標(biāo)題所在行的內(nèi)容
因此取得小標(biāo)題的關(guān)鍵代碼為:
index = ((((iStr.split("\n\n[0]).split('.'))[1]).split(' '))[1]
綜合前 2 項(xiàng)任務(wù),該腳本代碼如下(同時(shí)放在 GitHub 庫(kù)中):
#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)[1])
fout.close()
fin.close()
在命令行中執(zhí)行該腳本,即可完成批量切割任務(wù)。
任務(wù) 3: 批量轉(zhuǎn)換格式
這里需要使用 Pandoc[2],Debian 系 Linux 只要使用 apt-get 安裝即可:
$ sudo apt-get install pandoc
完成后,輸入 pandoc --version
查看是否安裝成功。
若安裝成功,只要下述命令,即可將 a.md
轉(zhuǎn)換為 a.doc
:
$ pandoc a.md -o a.doc -c Github.css
但是這只能實(shí)現(xiàn)單文件的格式轉(zhuǎn)換,若需要多文件的格式轉(zhuǎn)換,顯然需要批處理。對(duì) *nix 稍有了解的人很容易聯(lián)想到使用 bash shell 來(lái)解決這個(gè)問(wèn)題:
- 讀取目錄下的文件列表
- 對(duì)讀取的每個(gè)文件名執(zhí)行上述 pandoc 命令
由于事情緊急,因此查找網(wǎng)絡(luò)資料后,在命令行中輸入下述命令,完成文件格式批量轉(zhuǎn)換:[3]
注:下述操作均默認(rèn)在 50 個(gè) md 文件所在目錄下進(jìn)行
$ ls > aa.md
$ cat aa.md |while read line
> do
> pandoc $line -o $line.doc -c Github.css
> done
這樣基本完成了批量格式轉(zhuǎn)換問(wèn)題。但有 1 點(diǎn)不美:那就是在此操作下,得到的文件后綴是 .md.doc
而非 .doc
。如何解決這個(gè)問(wèn)題呢?最后我們就使用 rename
方法搭配簡(jiǎn)單的正則表達(dá)式,完成該任務(wù):[4]
rename 's/\.md.doc/\.doc/' *
相關(guān)代碼也已經(jīng)寫成 shell script 形式上傳到 GitHub 庫(kù)中.