
相信不少人都经历过这个场景用 LaTeX 写了几个月的论文公式排版漂亮得无可挑剔结果导师一句“投稿系统只收 Word”或者合作者发来一个 .docx 的模板让你“把内容填进去”瞬间心态就崩了。公式图片截图插入吧清晰度参差不齐行距还会被顶得乱七八糟用 MathType 一个一个重新敲吧几十上百个公式敲完估计还要再审一轮稿等于论文重写了一遍。我一开始也以为这个转换是个无解的难题直到我真正理解了 Word 公式的底层存储格式才发现这件事完全可以做到“一条命令搞定”甚至用 Python 三行核心代码就能把 LaTeX 公式精准转成 Word 原生公式。这篇文章不打算只丢给你一个工具链接就完事而是从原理到实操把我自己踩过坑后沉淀下来的完整方案写清楚。不管你是计算机专业的学生、正在写期刊论文的研究人员还是需要经常处理技术文档的工程师只要手上有 LaTeX 公式需要迁移到 Word这套流程都能让你的“格式焦虑”大幅缓解。我会先说明 Word 公式到底是怎么存放的再给出一个可以不依赖图形界面、直接用 Python 完成的转换链路最后附上我在批量处理论文时遇到的真实问题和对应的避坑经验。1. 为什么 LaTeX 公式进 Word 会这么折腾先搞懂两者的“语言”差异很多教程一上来就让你装工具、跑命令但遇到报错就抓瞎。其实要想转换过程可控你最需要先搞明白一个底层问题LaTeX 和 Word 在“数学公式”这件事上用的根本不是同一套记录语言。1.1 从“手抄公式”到“复制粘贴”一个典型的交稿场景我们先还原一个典型场景你用 LaTeX 写了一篇会议论文里面有行内公式如$\alpha \beta \gamma$有行间公式如\begin{equation} \theta^* \arg\min_{\theta} \sum_{i1}^{n} \mathcal{L}(f(x_i; \theta), y_i) \end{equation}源文件里这些内容都是一行一行的文本。但 Word 文档里一个公式不是“纯文本”能表示的。你按下Alt 插入一个公式后Word 会在内部生成一段特殊的 XML 标记语言叫做 OMMLOffice Math Markup Language。你看到屏幕上漂亮的分数符号、求和符号背后其实是一大段类似这样的东西m:oMath m:sSup m:e m:rm:tθ/m:t/m:r /m:e m:sup m:rm:t*/m:t/m:r /m:sup /m:sSup /m:oMath所以把一个 LaTeX 公式变成 Word 公式本质上不是“文本替换”而是要做一次数学表达式的语法翻译把 TeX 语法解析成数学结构树再按照微软定义的 OMML 规范输出。这也就是为什么单纯的“复制粘贴”永远行不通——因为 Word 不认识\frac{1}{2}这种写法。1.2 真正靠谱的转换思路找对翻译官既然公式的存储语言不同那么可行的方案就有两种走 GUI打开 MathType、Pandoc 或者在线转换网站把公式一个一个处理。走后端用 Pandoc 这类工具它在内部集成了一个叫 texmath 的库可以直接把 LaTeX 解析成 OMML然后嵌入 Word 文档中。Pandoc 的核心逻辑是“万能文档转换器”。它收到 LaTeX 输入后会先把文档解析成一份中间表示AST再根据目标格式的不同输出为 Word、HTML、Markdown 等。对于公式它内部调用 texmath将 LaTeX 公式的语法树映射到 Word 的 OMML 树。这就是它能够“无损伤”转换公式的根本原因。理解了这一点你就能明白为什么我强烈建议用 Pandoc 而不是截图或 MathType 手动敲因为 Pandoc 走的是结构转换而不是像素转换。结构转换意味着转换后的公式仍然是 Word 原生公式可以在 Word 里继续编辑、编号、更新域排版行为与手动输入的公式完全一致。2. 先认识 Word 公式的真身OMML 和为你代劳的 Pandoc 引擎在动手写代码之前我建议你用一个小示例感受一下“公式在 Word 里的真面目”这能省掉后面大量迷茫的时间。2.1 OMMLWord 公式的“母语”Word 公式相关的 XML 标签通常以m:为前缀核心标签包括标签含义常见的 LaTeX 对应物m:oMath一个数学公式区块$...$或\[...\]m:f分数结构\frac{分子}{分母}m:sSup上标结构x^2m:sSub下标结构x_im:nary大型运算符\sum、\int、\prodm:d括号定界符\left( \right)在.docx文件中正文内容存储在word/document.xml里。一个段落可能是普通文字也可能嵌入了多个m:oMath节点。Word 渲染这些节点时会根据字体、字号以及数学排版规则比如斜体、间距自动调整外观。这意味着只要 OMML 节点正确Word 就能像显示自己输入的公式一样显示它。2.2 为什么 Pandoc 是这条链路里最省事的“翻译官”Pandoc 本身是一个 Haskell 编写的命令行工具但它提供了非常友好的接口。对文档转换它有两类输入模式直接转换整个文档pandoc paper.tex -o paper.docx只转换公式片段用pandoc -f latex -t docx配合--mathml或默认的输出方式自动生成 OMML。对我们来说最省心的一点是Pandoc 转换生成的公式直接在 Word 里就是“公式对象”而不是图片也不是纯文本。你可以继续用 Word 的公式编辑器修改它它可以被 EndNote / Zotero 的域代码正常引用也不存在缩放失真问题。我在实际项目里最常用的一条命令是这样pandoc input.tex -o output.docx --mathml --standalone不过这条命令还依赖一定的 LaTeX 支持如果文档结构复杂推荐拆分子文件处理。下面我重点讲的是直接用 Python 调用 Pandoc 的思路因为大多数人的诉求其实是“我有一段 LaTeX 公式字符串我想把它放到一个已有的 Word 文档里”而不是“我有一整份 LaTeX 文档要整体变身”。3. 三行核心代码Python 调用 Pandoc 实现公式级转换“三行代码”到底怎么实现的我先把核心逻辑拆给你看再给一个可以直接运行的实例。3.1 为什么用 Python 而不是手动敲 Pandoc 命令命令行直接敲 Pandoc 当然很快但每次都要处理文件路径、临时文件、编码问题。而用 Python 包装一层你可以做到把一段 LaTeX 公式字符串直接转成 OMML 片段批量处理 Word 文档中的公式占位符把转换逻辑集成进自己的论文写作工作流。换句话说Python 在这里是“胶水”负责把 Pandoc 输出的 OMML 片段准确地塞进.docx文件。3.2 完整示例从 LaTeX 字符串到 Word 公式先安装依赖pip install python-docx pypandoc再安装 Pandoc 引擎。Windows 下可以用安装包macOS 下可以用 Homebrewbrew install pandoc然后看这个 Python 脚本。它做了三件事调用 Pandoc 把 LaTeX 公式转成 OMML、打开一个现有 Word 文档、在文末追加一个公式段落。import pypandoc from docx import Document from docx.oxml import parse_xml from docx.oxml.ns import nsmap # 核心代码LaTeX 公式转 OMML只用了三行 tex_formula r\theta^* \arg\min_{\theta} \sum_{i1}^{n} \mathcal{L}(f(x_i; \theta), y_i) omml_str pypandoc.convert_text( tex_formula, todocx, formatlatex, outputfiletemp_formula.docx, extra_args[--mathml] ) doc Document(temp_formula.docx) # 获取临时文档中的 OMML 节点 omml_element None for para in doc.paragraphs: for child in para._element: if child.tag.endswith(}oMath): omml_element child break if omml_element is not None: break # 把 OMML 节点插入到目标 Word 文档的指定位置 target_doc Document(target.docx) target_para target_doc.add_paragraph() target_para._element.append(omml_element) target_doc.save(output.docx)这段代码的核心就三行omml_str pypandoc.convert_text(tex_formula, todocx, formatlatex) doc Document(temp_formula.docx) omml_element ...思路是Pandoc 先把含公式的最小 LaTeX 文档转成一个临时 docx我们再去这个临时文档里把 OMML 节点挖出来插入目标文档的段落里。这样就能在不破坏 Word 原有内容的情况下精确地嵌入公式。3.3 如果只想用命令行也有等价的“一条龙”写法如果你不想写 Python其实 Pandoc 直接就能把“只有公式”的.tex文件转成带公式的.docxecho \theta^* \arg\min_{\theta} \sum_{i1}^{n} \mathcal{L}(f(x_i; \theta), y_i) formula.tex pandoc formula.tex -o formula.docx打开formula.docx你会看到公式已经完整渲染成 Word 原生格式。这背后就是 pypandoc 在做同样的事。如果你平时只是零散地转一两个公式命令行确实够了但如果要写进批量处理脚本Python 包装是更稳的选择。4. 不依赖 Pandoc 的备选方案纯 Python 库 latex2mathml mathml2ommlPandoc 方案虽然爽但有个前提你的环境里得有 Pandoc 这个外部程序。如果是内网环境、或者不能用包管理工具装东西那我们可以退而求其次用纯 Python 库实现同样的转换。这条路的核心也很有意思我顺手分享一下因为它能帮你进一步理解转换的本质。4.1 latex2mathml 和 mathml2omml 的分工这条链路由两个库配合完成latex2mathml把 LaTeX 公式字符串解析为 MathML数学标记语言XML 字符串。mathml2omml把 MathML 转换成 Word 能识别的 OMML。组合起来加个前缀后缀就能得到可插入 Word 的m:oMath节点。安装命令pip install latex2mathml mathml2omml示例代码import latex2mathml.converter import mathml2omml latex_str r\frac{\partial f}{\partial x} \lim_{h \to 0} \frac{f(xh)-f(x)}{h} mathml_str latex2mathml.converter.convert(latex_str) omml_str mathml2omml.convert(mathml_str) print(omml_str[:500])注意latex2mathml返回的只是 MathML 片段不是完整的 XML 文档。在mathml2omml转换时它会自动处理命名空间输出 OMML 的m:oMath节点。拿到omml_str之后同样可以把这段 XML 字符串解析成元素插入到python-docx的段落里from docx import Document from docx.oxml import parse_xml target_doc Document(target.docx) new_para target_doc.add_paragraph() # 注意omml_str 已经是完整的 m:oMath 标签 omml_element parse_xml(omml_str) new_para._element.append(omml_element) target_doc.save(output_pure_python.docx)这个方案的优点是零外部依赖适合脚本化量产缺点是latex2mathml对较新的 LaTeX 宏包、\boldsymbol、\bm、自定义命令的支持有限。遇到不认识的控制序列它可能会直接抛异常或输出不可读的结果需要搭配一些文本预处理。4.2 两个方案的对比对比维度Pandoc 方案latex2mathml mathml2omml 方案公式语法支持度高底层有 texmath 解析器中基础公式没问题复杂宏需处理外部依赖需要安装 Pandoc纯 Python适合内网环境输出稳定性高社区维护成熟一般有些边界情况会翻车适合场景完整文档转换、高质量公式批量脚本、离线环境、简单公式我自己主力用 Pandoc但在某些服务器上没法装 Pandoc所以我保留了第二套纯 Python 链路作为兜底。两条路我都在生产环境里跑过会根据项目情况灵活选。5. 实战进阶把 LaTeX 公式批量灌进整篇 Word 论文公式单独能转了接下来更进一步怎么把一整篇 LaTeX 论文或大量公式占位符批量转换成 Word 里排好版的公式段落。这里面有几个坑跟 Word 的样式机制强相关。5.1 从“一个公式”到“整篇文档”的问题拆解大多数人的需求不是转一个公式而是“论文里几十个公式全给我转完”。这时候如果你逐个人工复制公式再跑 Pandoc会累死。更好的方式有两种方式一直接在 LaTeX 源文件级别整体转换用pandoc paper.tex -o paper.docx一次性拿到包含全部公式的 Word 文档。方式二先用占位符标注 Word 文档里的公式位置再用 Python 扫描并替换。方式一适合“从零开始迁移”整体排版不一定完美但公式一定没问题方式二适合“已经有 Word 草稿只想把草稿里的$$...$$文本块替换成真公式”。我举个方式二的脚本框架import re from docx import Document from docx.oxml import parse_xml import pypandoc def latex_to_omml_element(latex_str: str): # 用临时文件方式获取 OMML pypandoc.convert_text(latex_str, docx, formatlatex, outputfiletmp.docx) temp_doc Document(tmp.docx) for para in temp_doc.paragraphs: for child in para._element: if child.tag.endswith(}oMath): return child return None doc Document(draft.docx) pattern re.compile(r\$\$(.?)\$\$, re.S) for para in doc.paragraphs: if $$ not in para.text: continue # 注意python-docx 默认无法直接按 run 替换复杂 XML需要操作底层 XML # 这里简化处理清空段落然后重新插入文字和公式节点 text para.text parts pattern.split(text) para.clear() for i, part in enumerate(parts): if i % 2 0: if part: para.add_run(part) else: omml latex_to_omml_element(part) if omml is not None: para._element.append(omml) doc.save(draft_filled.docx)这段代码有几个地方要额外注意para.clear()会把原有排版格式如字体、字号清掉所以对特殊样式的段落最好先记录样式再重设。pypandoc.convert_text每次调用都生成临时文件批量处理时会有 IO 开销建议缓存已经转换过的公式字符串。Word 段落里如果同时有普通文字和多个公式节点插入顺序必须保持普通 run 和m:oMath交错出现。因为 Word 的文档模型就是“段落内由多个内容节点序列组成”。5.2 真实踩坑Word 表格里的公式别用老办法插我在处理一篇实验论文时发现大量公式出现在表格的“参数说明”列里。用上面的循环扫描para完全没效果因为表格里的内容根本不在doc.paragraphs里而是嵌套在w:tbl的各个w:tc单元格里。正确做法是递归访问文档体所有块级容器from docx.document import Document as Doc from docx.table import Table from docx.text.paragraph import Paragraph def iter_block_items(parent): parent_elm parent.element.body for child in parent_elm.iterchildren(): if child.tag.endswith(}p): yield Paragraph(child, parent) elif child.tag.endswith(}tbl): yield Table(child, parent) for block in iter_block_items(doc): if isinstance(block, Table): for row in block.rows: for cell in row.cells: for para in cell.paragraphs: # 在这里对每个段落做公式替换 pass这一步花了我半个晚上才发现问题所在python-docx的默认paragraphs属性不递归表格。如果你要写“整篇文档公式替换”的脚本这个细节必须记录在案否则会漏掉一多半公式而不自知。5.3 字体与样式的后续微调公式插入完成后Word 里公式的字体、大小通常默认走 Word 的“Cambria Math”字体。这跟 LaTeX 里的 Computer Modern 字体会有视觉差异。如果你对字体要求特别严格可以在 Word 里统一调整公式样式选中全部公式用“查找和替换”里的“特殊格式”不好区分公式建议全选文档后在公式选项卡里改。或在stylesheet.xml中为 OMML 设置默认字体属性。实际操作中我一般不会为了追求视觉完全一致去折腾公式字体因为学术期刊最终会统一排版。只要公式结构正确、运算符清晰、大小写斜体正确字体差异通常是可以接受的。6. 翻车清单哪些 LaTeX 写法会让转换结果面目全非这部分是我最想说的因为网上教程只会告诉你“按这个命令就能成功”但真实项目里十个公式有八个会触发意外。我把最常见的坑整理成一份清单你看完可以少走很多弯路。6.1 常见翻车点一览翻车场景问题描述推荐处理方式自定义宏命令\newcommand定义的控制序列Pandoc 不一定认识先手动展开宏或把宏定义放在单独文件里用\input包含Pandoc 会尝试解析一部分\boldsymbol与\bm不同宏包提供的粗体命令解析结果不稳定换成\mathbf或直接转换后再在 Word 中手动加粗\operatorname{argmin}有时会变成字母序列而非上下限结构改用\arg\min或使用\mathrm{argmin}也能在 Word 里显示成普通文本\begin{aligned}环境行间公式里有多个对齐点Word 转换后可能丢失对齐转为\begin{array}{ll}或直接接受单行拆分中文注释或文本Pandoc 处理%注释里的中文有时会编码报错转换前用脚本清理注释\tag{}公式编号Word 中公式编号不是自动生成的而是文本节点转换后用 Word 的“编号”功能重新设置\left( \right)跨行自动调整大小的括号在 Word 中可能变成普通括号手动检查所有括号必要时用 Word 公式工具重新调整6.2 为什么有的公式转换后“长得不像”根因是语义树不同举个例子LaTeX 的\sum_{i1}^{n}在语义上是一个“大型运算符 上下标”。Word 的 OMML 用m:nary表示。但如果你写的是\sum_{i1}^n而 LaTeX 解析器把它识别成了“普通字符 上标 下标”那转换后 Word 里就会显示成Σ然后右上角n、右下角i1而不是我们期望的上下限分布。这属于TeX 语法解析歧义。Pandoc 的 texmath 底层做了很多标准化处理但某些写法仍然受上下文影响。我的建议是转换前尽量把公式写成规范形式该加花括号就加花括号例如\sum_{i1}^{n}不要省略花括号。转换后抽查所有大型运算符、分数、根式确认结构自动调整正确。6.3 从源头减少翻车调整 LaTeX 写法的习惯如果你还没开始写论文但从现在起就希望以后能平滑转 Word那么在 LaTeX 源码层面可以做几件小事不要过度依赖自定义宏或者把所有宏定义集中放一个文件并附上展开版公式编号用自动编号环境如equation少用手动\tag多用标准控制序列少用\stackrel、\overset等生僻命令注释用英文避免中文注释干扰解析不要把样式类设置写在\documentclass里Pandoc 主要关注正文内容。这些习惯对纯 LaTeX 写作没有副作用但在转换时会给你省下大量排查时间。我后来写新论文都会尽量遵守这套规则因为“不知道哪一刻就需要交付 Word 版”。7. 后续演进公式以外图表与交叉引用也能一并处理既然你已经把公式链路打通了我再顺手扩展一下很多人的“格式无忧”需求不只是公式还有图、表、交叉引用。Pandoc 在这些方面虽然不如公式完美但也能帮上忙。7.1 图片与表格的转换策略LaTeX 文档中转 Word图片的引用路径、表格的浮动环境table,figure都需要重新映射。Pandoc 会把\includegraphics转成 Word 的图片节点通常保留原图文件表格会转成 Word 表格但宽度、对齐、合并单元格的细节可能丢失。我一般会这样做先用 Pandoc 整体转换拿到一个粗略的 Word 版本。再检查目录、图表编号、交叉引用手动微调。如果图片是矢量图PDF 或 EPS建议提前转换成高分辨率 PNG 或 SVG 再插入。Word 对 SVG 的支持已经有改进但学术论文要求高时我更推荐用 300 DPI 的 PNG 插入保证打印清晰度。7.2 交叉引用与自动编号Word 域的重新搭建LaTeX 的\ref{}和\label{}机制转换成 Word 后并不会自动生成 Word 的交叉引用域。Pandoc 默认会输出静态文本编号而不是动态域。如果需要“正文中点击‘图 1’跳到对应图片”的效果需要在 Word 里重新插入交叉引用。批量处理交叉引用是比较高级的需求目前没有完全自动化的开源方案。我见过有人用 VBA 宏做二次处理但维护成本不低。建议根据期刊要求判断如果最终要提交 PDF其实静态引用编号也能接受如果要在 Word 中继续编辑则可以先把导航结构调整好再说。8. 我的实操心得与方法论沉淀最后聊点我个人在多次项目里得出的判断。网上关于“LaTeX 转 Word”的讨论很多有人说“直接用 Pandoc 一键搞定”也有人说“公式转换就是个伪命题还是手动敲吧”。这两种说法都太极端了。真实情况是基础公式和中等复杂度的公式Pandoc 能给你极高的完成度但涉及复杂宏包、特殊排版和自动编号时你需要有“转换后必然要人工检查一轮”的心理预期。我的建议排序是能用 Pandoc 就用 Pandoc它是对公式语义理解最成熟的开源工具没有之一。如果只转公式片段用 Python 包装的链路最灵活能嵌入批处理流程。纯 Python 库方案作为兜底离线也能跑。转换后的手动检查重点放在大型运算符、括号匹配、上下标位置、粗体斜体、公式编号。我自己现在的工作流是手写 LaTeX 论文 → 用 Pandoc 出一版 Word → 用 Python 脚本把表格里的公式和特殊位置补一遍 → Word 里做最终样式微调。整个过程从过去的一整天压缩到了一小时以内。最值钱的不是某一条命令而是理解了公式在两种格式里各自的“底层表达”一旦框架对了很多问题都能举一反三。如果你也在为论文投稿、报告协作、课程作业里的公式迁移头疼可以照着这篇文章的环境配置和代码跑一遍。遇到具体的转换失败案例欢迎带上 LaTeX 源码来交流我可以帮你分析是语法解析问题还是 OMML 兼容性问题。实践一次比看十篇教程都管用。