实际问题
将一个文件中的相似块分割成若干个文件。比如下面这个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 第一回: 灵根育孕源流出 心性修持大道生 这是第一段内容..... 这是第二段内容..... 这是第三段内容..... 更多... 第二回: 悟彻菩提真妙理 断魔归本合元神 这是第一段内容..... 这是第二段内容..... 这是第三段内容..... 更多... 第三回: 四海千山皆拱伏 九幽十类尽除名 这是第一段内容..... 这是第二段内容..... 这是第三段内容..... 更多...
|
假设有一个长篇小说txt文件,每一回有相似的结构。要解决的问题是:如何将每一回分割成单独的文件?文件名是每一回的标题,文件的内容就是每一回的内容。
解决思路
解决这种实际的问题,我的思路一般是:用人的思维找到直观的解决办法。然后,将人的思维转换成对应的代码逻辑,比如:运用什么控制语句?使用什么数据结构?涉及什么特殊算法?等等。
首先我们从人的思维出发考虑如何解决这个问题。最直接的方法是:根据开头“第一回:”这几个字确定这一回的标题,然后确定接下来直到“第二回:”之间的部分为第一回的内容。然后将第一回的内容写到以标题命名的文件中。接下里,以此类推,直到最后没有内容。
接下来,思考如何将这个过程转化成代码的逻辑。
显然,这里是循环判断的逻辑,循环的范围是从第一行到最后一行。分析过程如下:
- 搜索第一行,是标题行,记录标题并移到下一行。
- 搜索这一行,不是标题行,记录行首的位置start。判断下一行是否是标题行,不是则移到下一行。
- 重复过程2,直到当前行的下一行是标题行时,记录本行行首的位置end。
- 将start和end之间的内容写到以标题命名的文件中。移到下一行。
- 重复上面的过程1,2,3,4。直到光标到达最后。
代码实现
根据上面的分析过程,有如下的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| (defun my-split-file (file) (interactive "fchoose a file: ") (let ((filedir "~/test-dir/") filename start end content) (with-current-buffer (get-buffer-create "*split-file*") (insert-file-contents file) (goto-char (point-min)) (while (< (point) (point-max)) (if (search-forward-regexp "^第.+回:" (line-end-position) t) (progn (setq filename (string-trim (thing-at-point 'line))) (next-line) (beginning-of-line) (setq start (point))) (save-excursion (next-line) (beginning-of-line) (when (or (search-forward-regexp "^第.+回:" (line-end-position) t) (= (point) (point-max))) (previous-line) (end-of-line) (setq end (point)) (setq content (buffer-substring-no-properties start end)) (with-temp-file (concat filedir filename ".txt") (insert content)) )) (next-line) (beginning-of-line))))))
|