能够使用Python正则表达式函数的文本处理工具——Calibre电子书编辑器

大多数文本文件编辑工具在查找替换时都可以使用正则表达式,但无法像在使用Python的re库时那样使用正则表达式函数完成替换。作为经常使用Calibre编辑EPUB书籍的用户,有一次,在制作Anki笔记导入文件时,我突发奇想,何不把文本文件导入Calibre电子书编辑器,不就可以在处理文本文件时使用正则表达式函数了吗?立即付诸行动:

双击Calibre套件中的"ebook-edit.exe",然后:

试着编写了两个正则表达式函数。第一个用于检查题目的编号与行号是否一致,从而判断是否成功让每一题占据了一行(处理后的文件每个字段均用西文双引号包裹,字段之间使用西文逗号分隔):

python 复制代码
# 查找栏填写(?s)^.+,光标定位在文档开头或者先按Ctrl+A,点击查找,确保匹配了全文,再按替换
 
def replace(match, number, file_name, metadata, dictionaries, data, functions, *args, **kwargs):
    import re
    
    full_text = match.group(0) # 取得文件全部文本
    # 按换行切,拿到真实行列表
    lines = full_text.splitlines()
 
    err = ''        
    for lineno, line in enumerate(lines, start=1):
        if line.startswith('"'):
            line = line[1:]  # 如果行首已经添加了引号则剔除
        serial = re.search(r'^\d+', line).group(0)
        if serial != str(lineno):
            err = f"行{lineno}出错: {line[:8]},可搜索{lineno}进行修改"
            break #只要某一行序号与行号对不上,后面的就全部对不上,因此,找到第一个对不上的就可以终止并更正了
    if err == '':
        print('行号全部正确')
    else:
        print(err)
    return full_text  #实际上没有替换任何字符

第二个正则表达式函数用于检查处理后的文件每行的字段数量是否与Anki模板的字段数量完全一致(新版Anki在文本文件的字段数量与模板中的字段数量不一致时会丢弃多余字段或者用空字符串补充缺失字段而不是报错,做这个检查可以避免出现非预期的导入结果):

python 复制代码
# 查找栏填写^.+$,点击替换所有
 
def replace(match, number, file_name, metadata, dictionaries, data, functions, *args, **kwargs):
    import csv
    from io import StringIO
    
    sep = ','  # 字段分隔符
    fields_count = 5 # 预期字段数
    preview_chars = 8 # 出错信息中截取的行首字符数量
    
    # 持久化保存行号及对应行的出错信息,无错误则信息为None
    if 'errs' not in data: 
        data['errs']=[]
        data['errs'].append({'lineno': 0, 'msg': None})
    
    if match is None :
        error_list = []
        for err_info in data['errs']:
            if err_info['msg'] is not None:
                error_list.append(f"行{err_info['lineno']}出错:{err_info['msg']}")
 
        if error_list:
            print("\n".join(error_list))
        else:
            print('恭喜,所有行字段数量全部正确!')
 
        return
    
    else:
    
        line = match.group(0)
        lineno = data['errs'][-1]['lineno'] + 1
        
        reader = csv.reader(StringIO(line), delimiter=sep)
        for r in reader:
            if len(r) != fields_count:                
                msg = f"{line[:preview_chars]}...,预期字段数量{fields_count},实际字段数量{len(r)}"
                data['errs'].append({'lineno': lineno, 'msg': msg})
            else:            
                data['errs'].append({'lineno': lineno, 'msg': None})
        return line
 
# 开启全部匹配结束后额外调用一次 replace(match=None),输出相关结果
replace.call_after_last_match = True

当然,第二个函数还有像第一个那样一次性获取整个文档文本后再处理的写法(看起来代码更精炼):

python 复制代码
# 查找栏填写(?s)^.+,光标定位在文档开头或者先按Ctrl+A,点击查找,确保匹配了全文,再按替换

def replace(match, number, file_name, metadata, dictionaries, data, functions, *args, **kwargs):
    import csv
    from io import StringIO
    if match is None :return
    
    full_text = match.group(0)
    # 按换行切,拿到真实行列表
    lines = full_text.splitlines()

    sep = ','  # 字段分隔符
    fields_count = 5 # 预期字段数
    preview_chars = 8

    err = []
    
    for lineno, line in enumerate(lines, start=1):
        r = next(csv.reader([line], delimiter=sep))
        if len(r) != fields_count:
            err.append(f"行{lineno}: {line[:8]}...,预期字段数量{fields_count},实际字段数量{len(r)}")
    if len(err) > 0:
        print(f"❌ 共发现{len(err)}行字段数量错误:")
        print("\n".join(err))
    else:
        print("✔ 恭喜!所有笔记字段数量均正确!")
    return full_text

第一个函数也有每次读取一行进行处理的写法,这里就省略了。一次获取文档全部内容的写法在操作上要确保先用查找匹配到整个文件范围,再点击替换,每次读取一行的写法则无需这个前提条件,直接点击"替换所有"按钮即可。

关于Calibre编辑器中正则表达式函数更详细的知识参阅:Calibre编辑器中的函数模式搜索替换技术详解-CSDN博客

相关推荐
全栈陈序员14 小时前
【Python】基础语法入门(二十九)—— 正则表达式实战:文本处理利器
开发语言·人工智能·python·正则表达式
BruceXu6 天前
\b 在中文里会静默失效:三个正则坑和一份能用的字符边界方案
正则表达式
阿昭L8 天前
正则表达式
正则表达式·编译原理
波力海苔夹心脆6758 天前
C# 正则表达式零基础入门:从“看得懂“到“会用“
经验分享·后端·mysql·正则表达式·c#
FRing039 天前
JavaScript入门到精通二十四(正则表达式、元字符、修饰符)
开发语言·前端·javascript·正则表达式
小白快快跑哦11 天前
python-字符串全解(六):正则表达式-元字符与转义
python·正则表达式·字符串·元字符·转义
小白快快跑哦13 天前
python-字符串全解(六):正则表达式-逻辑运算或
python·正则表达式·字符串·逻辑运算
MoRanzhi120313 天前
106.正则问题(分治)
python·算法·正则表达式·蓝桥杯·递归·分治算法·字符串处理
临床数据科学和人工智能兴趣组14 天前
在R语言的生态系统中,字符串处理一直是一个重要且复杂的任务
开发语言·正则表达式·r语言·r语言-4.2.1