# MDX文本修订批量替换

**URL:** <https://forum.freemdict.com/t/topic/3302>\
**Category:** 技术交流与词典编修\
**Tags:** 词典软件制作\
**Created:** [2020 年9 月 15 日 05:55 UTC](https://forum.freemdict.com/t/topic/3302 "2020-09-15T05:55:26Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

作者： ![last\_idol](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/last_idol/32/2205_2.png) [@last\_idol](https://forum.freemdict.com/u/last_idol)\
发布日期： [2020 年9 月 15 日 05:55 UTC](https://forum.freemdict.com/t/topic/3302/1 "2020-09-15T05:55:26Z")

</div>

新尝试单独开一贴。  
MDX的修订，现在大多还是手工+正则的形式一条条替换，此贴尝试用 patch文本的形式解决批量替换的问题。

以下面这个 MDX 原始文本为例：

```auto
down
<span>Get down off the taable.</span>
</>
float
<span>I wasn’t sure if the raft would float.</span>
</>

```

上面的 taable 需要替换成 table，另外我们加个需求，所有 span 外加上div 标签，这里使用正则。

Patch文本的组织形式和 mdx 文本保持一致，用\</\>分开需要修的词头，第一行需要匹配的词头， 第二行是需要修的文本，第三行是替换文本， patch文本的格式：

```auto
down
the taable
the table
</>
*
(<span>(([\s\S])*?)<\/span>)
<div>$1</div>
</>

```

上面比较特殊的是，有个星号(\*)在第一行，这表示所有词头里替换，第二，三行用正则替换，完成span 外套 div。整个 patch 文本，按顺序执行。这些都可以手工修，问题是很繁琐，文本 patch的形式，会更清楚些，也方便分享，替换结果：

```auto
down
<div><span>Get down off the table.</span></div>
</>
float
<div><span>I wasn’t sure if the raft would float.</span></div>
</>

```

衍生处理，还可以替换词头，拆分词头之类的，实现的Python2脚本：

```auto
#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
import re

def read_text(path):
    with open(path, "r") as f: 
        text = f.read()
        return text

# run: python patch.py mdx.txt patch.txt
def main(argv):
    if len(sys.argv) != 3:
        sys.ext(2)
    
    mdx = read_text(sys.argv[1])
    items = []
    for item in [x.strip() for x in mdx.split("</>") if x.strip()]:
        i = item.find("\n")
        if i != -1:
            word = item[0: i].strip()
            content = item[i:].strip()
            items.append((word, content))

    rules = []
    for patch in read_text(sys.argv[2]).split("</>"):
        arr = patch.splitlines();
        arr[:] = [x.strip() for x in arr if x.strip()]
        if len(arr) == 3:
            rules.append((arr[0], arr[1], arr[2]))

    for rule in rules:
        match, r1, r2 = rule[0], rule[1], rule[2]
        r2 = r2.replace('$', '\\')

        for i, item in enumerate(items):
            word, content = item;
            if match == '*' or match == word:
                content = re.sub(r1, r2, content)
                items[i] = (word, content)

    with open("mdx_new.txt", "a") as f:
        for item in items:
            word, content = item
            f.write(word.strip())
            f.write("\n")
            f.write(content.strip())
            f.write("\n")
            f.write("</>\n")

if __name__ == " __main__":
   main(sys.argv[1:])

```

可以下载尝试，[patch.zip](https://forum.freemdict.com/uploads/short-url/95JPDjgidMJtAcxP6k0jtdfqyHe.zip) (2.5 KB)，包含 patch.py, mdx.txt, patch.txt 。

```auto
python patch.py mdx.txt patch.txt

```

会生成修订好的 mdx\_new.txt

---

<div class="post-metadata">

作者： ![endnote](https://forumcdn.freemdict.com/letter_avatar_proxy/v4/letter/e/9de0a6/32.png) [@endnote](https://forum.freemdict.com/u/endnote)\
发布日期： [2020 年9 月 15 日 08:28 UTC](https://forum.freemdict.com/t/topic/3302/3 "2020-09-15T08:28:08Z")

</div>

很好的想法。  
这个应该是面向脱离小白阶段的朋友了。  
请教个问题，如何在mdx编译前的txt里头发现没有正确闭合的标签？很多mdx是存在这样那样的毛病的。  
例如某一定义行少了个`</span>`，替换的结果甚至代码就可能会出现问题。所以，如果事先能检查`<span>`标签的闭合是最好了。

btw 论坛讨论氛围起来了，好事。

---

<div class="post-metadata">

作者： ![endnote](https://forumcdn.freemdict.com/letter_avatar_proxy/v4/letter/e/9de0a6/32.png) [@endnote](https://forum.freemdict.com/u/endnote)\
发布日期： [2020 年9 月 15 日 08:43 UTC](https://forum.freemdict.com/t/topic/3302/5 "2020-09-15T08:43:49Z")

</div>

w3c 的Validator貌似只能检查标准的HTML标签，而很多mdx使用了大量的自定义tag名称，然后在css定义是block还是inline。例如本论坛的cod9双解，只有极少数地方用div和span（其实其数据内容非常好，显示效果也不错，高度自定义）。  
有一些夸张的mdx，每个全角半角的括号逗号顿号句号都包上特定标签，看了代码都难受（但显示效果毫无问题）。

---

<div class="post-metadata">

作者： ![Vim](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/vim/32/8408_2.png) [@Vim](https://forum.freemdict.com/u/Vim)\
发布日期： [2020 年9 月 15 日 09:17 UTC](https://forum.freemdict.com/t/topic/3302/7 "2020-09-15T09:17:04Z")

</div>

可以使用Tidy，不限于HTML标签，自定义标签都是可以的。

> **[Tidy-HTML5用于mdx源文件的技巧 - 词库制作交流区 - Dictionary-Making - 掌上百科 - PDAWIKI - ...](https://www.pdawiki.com/forum/forum.php?mod=viewthread&tid=32432)**
>
> 看到@garypang 的如下帖子，介绍Tidy是个大杀器，能将html格式化的同时自动修复html里的错误：MDX词组提取 - 从正则进阶到头发护理 https://www.pdawiki.com/forum/foru ... Tidy-HTML5用于mdx源文件的技巧 ,掌上百科 - PDAWIKI

---

<div class="post-metadata">

作者： ![ankifyh](https://forumcdn.freemdict.com/letter_avatar_proxy/v4/letter/a/dfb087/32.png) [@ankifyh](https://forum.freemdict.com/u/ankifyh)\
发布日期： [2020 年9 月 15 日 09:25 UTC](https://forum.freemdict.com/t/topic/3302/8 "2020-09-15T09:25:36Z")

</div>

再有一点就是更新词典文件不一定要通过补丁文件,而是像安卓应用市场那样建立一个分发平台,词典更改后上传分发平台,用户通过终端程序对比本地词典文件和平台上的版本,通过计算对比后下载新增的那部分

---

<div class="post-metadata">

作者： ![endnote](https://forumcdn.freemdict.com/letter_avatar_proxy/v4/letter/e/9de0a6/32.png) [@endnote](https://forum.freemdict.com/u/endnote)\
发布日期： [2020 年9 月 20 日 11:36 UTC](https://forum.freemdict.com/t/topic/3302/12 "2020-09-20T11:36:01Z")

</div>

> [@近期 无更新](http://forum.freemdict.com/t/topic/3041/222):
>
> [文本批量替换工具.rar](https://forum.freemdict.com/uploads/short-url/qEhWZCp5BTTzATI71cYXPkA1vqJ.rar) (670.3 KB)
> 
> 文本批量 替换 超链接 一下子 就解决了 前提把 字典对好

给像我这样的小白转个GUI 工具  
[https://forum.freemdict.com/t/topic/3041/222](https://forum.freemdict.com/t/topic/3041/222)

---

<div class="post-metadata">

作者： ![last\_idol](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/last_idol/32/2205_2.png) [@last\_idol](https://forum.freemdict.com/u/last_idol)\
发布日期： [2020 年9 月 20 日 15:13 UTC](https://forum.freemdict.com/t/topic/3302/13 "2020-09-20T15:13:40Z")

</div>

除非用新格式，否则只能文本 patch，文本 patch 也只限于论坛上，词典作者们之间分享。

---

<div class="post-metadata">

作者： ![last\_idol](https://forumcdn.freemdict.com/user_avatar/forum.freemdict.com/last_idol/32/2205_2.png) [@last\_idol](https://forum.freemdict.com/u/last_idol)\
发布日期： [2020 年9 月 20 日 15:14 UTC](https://forum.freemdict.com/t/topic/3302/14 "2020-09-20T15:14:31Z")

</div>

这只是个测试脚本，不值得做 gui。
