Calibre编辑器中的函数模式搜索替换技术详解
引言
在电子书编辑过程中,经常需要对文本内容进行批量处理和转换。Calibre编辑器提供的"搜索与替换"功能中的函数模式(Function Mode)是一个非常强大的工具,它允许用户将正则表达式与Python函数结合使用,实现复杂的文本处理功能。
函数模式基础
函数模式与常规的搜索替换模式不同,它允许你使用Python函数来处理匹配到的文本,而不是简单的替换模板。这种模式提供了极大的灵活性,可以实现传统搜索替换无法完成的任务。
基本工作原理
- 首先指定一个正则表达式来匹配文本
- 然后提供一个Python函数来处理所有匹配到的文本
- 函数接收匹配对象作为输入,返回处理后的文本
实用案例解析
案例1:自动修正标题大小写
问题:电子书中的标题大小写不规范,需要统一为标题格式。
解决方案:
Find expression: <([Hh][1-6])[^>]*>.+?</\1>
使用内置的"Title-case text (ignore tags)"函数,可以将类似<h1>some titLE</h1>
的标题转换为<h1>Some Title</h1>
,即使标题中包含其他HTML标签也能正确处理。
案例2:智能替换连字符
问题:需要将普通连字符替换为更专业的em-dash(长破折号)。
解决方案:
def replace(match, number, file_name, metadata, dictionaries, data, functions, *args, **kwargs):
return match.group().replace('--', '—').replace('-', '—')
使用正则表达式>[^<>]+<
可以确保只在文本内容而非HTML标签内进行替换。
案例3:修复断词错误
问题:扫描版电子书中常有错误的断词(如行末断开的单词)。
解决方案:
import regex
from calibre import replace_entities
from calibre import prepare_string_for_xml
def replace(match, number, file_name, metadata, dictionaries, data, functions, *args, **kwargs):
def replace_word(wmatch):
without_hyphen = wmatch.group(1) + wmatch.group(2)
if dictionaries.recognized(without_hyphen):
return without_hyphen
return wmatch.group()
text = replace_entities(match.group()[1:-1])
corrected = regex.sub(r'(\w+)\s*-\s*(\w+)', replace_word, text, flags=regex.VERSION1 | regex.UNICODE)
return '>%s<' % prepare_string_for_xml(corrected)
这个函数会检查连字符连接的单词,如果合并后的单词在词典中存在,则自动合并。
案例4:自动编号章节
问题:需要为所有h2标题添加自动编号。
解决方案:
def replace(match, number, file_name, metadata, dictionaries, data, functions, *args, **kwargs):
section_number = '%d. ' % number
return match.group(1) + section_number + match.group(2)
replace.file_order = 'spine'
使用正则表达式(?s)(<h2[^<>]*>)(.+?</h2>)
可以匹配所有h2标签,并自动添加递增的编号。
高级功能
自动生成目录
通过更复杂的函数,可以扫描文档中的所有标题并自动生成目录:
from calibre import replace_entities
from calibre.ebooks.oeb.polish.toc import TOC, toc_to_html
from calibre.gui2.tweak_book import current_container
from calibre.ebooks.oeb.base import xml2str
def replace(match, number, file_name, metadata, dictionaries, data, functions, *args, **kwargs):
if match is None:
if 'toc' in data:
toc = data['toc']
root = TOC()
for (file_name, tag_name, anchor, text) in toc:
parent = root.children[-1] if tag_name == 'h2' and root.children else root
parent.add(text, file_name, anchor)
toc = toc_to_html(root, current_container(), 'toc.html', 'Table of Contents for ' + metadata.title, metadata.language)
print(xml2str(toc))
else:
print('No headings to build ToC from found')
else:
if 'toc' not in data:
data['toc'] = []
tag_name, anchor, text = match.group(1), replace_entities(match.group(2)), replace_entities(match.group(3))
data['toc'].append((file_name, tag_name, anchor, text))
return match.group()
replace.call_after_last_match = True
replace.file_order = 'spine'
函数API详解
所有函数模式函数都必须遵循特定的Python函数签名:
def replace(match, number, file_name, metadata, dictionaries, data, functions, *args, **kwargs):
return a_string
参数说明
- match:匹配对象,包含正则匹配的所有信息
- number:当前匹配的序号(从1开始)
- file_name:匹配所在的文件名
- metadata:电子书的元数据(标题、作者等)
- dictionaries:拼写检查词典
- data:持久化字典,可用于在多次匹配间共享数据
- functions:访问其他用户定义函数
特殊属性
- file_order:控制多文件处理顺序('spine'或'spine-reverse')
- call_after_last_match:是否在所有匹配完成后额外调用一次函数
- append_final_output_to_marked:是否将最终输出追加到标记文本
- suppress_result_dialog:是否抑制结果对话框
调试技巧
在函数中使用print()
语句输出调试信息,这些信息会在操作完成后显示在弹出窗口中。这对于检查中间结果和调试复杂函数非常有用。
最佳实践
- 对于简单任务,优先使用内置函数
- 复杂处理时,先在小范围测试函数效果
- 充分利用
data
字典在多次匹配间共享数据 - 对于多文件操作,设置正确的
file_order
- 处理完成后需要汇总结果时,使用
call_after_last_match
结语
Calibre编辑器的函数模式搜索替换功能为电子书编辑提供了强大的自动化处理能力。通过结合正则表达式和Python编程,几乎可以实现任何文本处理需求。从简单的文本替换到复杂的结构重组,这一功能都能胜任,是电子书编辑和整理的利器。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考