MDX文本修订批量替换

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

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

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文本的格式:

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

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

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脚本:

#!/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 (2.5 KB),包含 patch.py, mdx.txt, patch.txt 。

python patch.py mdx.txt patch.txt

会生成修订好的 mdx_new.txt

6 个赞

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

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

1 个赞

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

1 个赞

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

3 个赞

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

1 个赞

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

1 个赞

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

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