LaTeX 如何减少重复代码?使用自定义命令、环境与 \input

博客EasyLaTeX发布于

在 LaTeX 项目中减少重复代码,可以从三个方面入手:用自定义命令复用相同格式,用环境复用固定的内容结构,再用 \input 管理多个文件共用的代码。并不是所有重复内容都值得封装,建议优先处理出现多次、写法一致且后续可能一起修改的部分。

同一格式反复手写时:定义带参数的命令

下面这份源码可以直接编译,\vect、\code、\R 各定义一次,正文反复调用:

\documentclass[11pt]{article}
\usepackage{amsmath,amssymb}
\newcommand{\vect}[1]{\boldsymbol{#1}}
\newcommand{\code}[1]{\texttt{#1}}
\newcommand{\R}{\mathbb{R}}
\begin{document}
For $\vect{x}\in\R^d$, open \code{main.tex}.

\end{document}

定义写在 \begin{document} 之前,全文都能调用;写在正文中,只有它之后的内容能用。命令名与已有宏包撞车时会报 ! LaTeX Error: Command \R already defined.,换名即可;要覆盖已有定义时用 \renewcommand,仅在命令未定义时提供默认值可用 \providecommand。

\newcommand 最多接受 9 个参数;参数到四五个时,调用处要对着定义才能看懂。

同一结构反复出现时:定义环境

论文里几十个格式相同的表格适合抽成一个环境。下面的 resulttable 接受列格式和表头行两个参数:

\documentclass[11pt]{article}
\usepackage{booktabs}
\newenvironment{resulttable}[2]{%
  \begin{table}[htbp]\centering
  \begin{tabular}{#1}\toprule
  #2\\\midrule
}{%
  \bottomrule\end{tabular}
  \end{table}
}
\begin{document}
\begin{resulttable}{lcc}{Model & Accuracy & F1}
Baseline & 0.812 & 0.794 \\
Ours & 0.867 & 0.851 \\
\end{resulttable}
\end{document}

之后每张表只写数据行,\toprule、列格式、浮动体位置都由环境提供。

环境体内部出错时,日志报的行号是展开之后的位置,与源码行号对不上;这时先把这段定义和一个最小调用单独放进测试文件编译,定位到具体行再放回主文档。

多个文件共用片段时:拆出公共文件

同一段导言区被几个文件各抄一份时,用 \input 解决。

preamble.tex:

\usepackage{amsmath,amssymb}
\newcommand{\vect}[1]{\boldsymbol{#1}}

main.tex:

\documentclass{article}
\input{preamble}
\begin{document}
$\vect{x}$
\end{document}

\input 是纯插入,本例把 main.tex 放在项目根目录,路径以编译时的项目根目录为基准,而不是写这行 \input 的章节文件位置;在 chapters/intro.tex 里写 \input{intro2} 会报文件找不到,要写成相对主文件的 chapters/intro2。

章节级拆分用 \include 更合适:前后自动 \clearpage,每章生成独立的 .aux,配合 \includeonly 可以只编译改动的章节;\include 不能嵌套。

封装之前先确认:三类片段才值得收敛

封装有成本,三条同时满足才动手:出现三次以上、每次内容一致(而不只是看起来相似)、以后会一起改。

只出现两次的段落封装之后,读者要跳到另一个文件才能看懂;各处有细微差异的片段强行统一,要加一排开关参数,调用处比原文更难读。

改完之后:编译并复核关键位置

编译一次,核对三处:定义文件是否在 \begin{document} 之前被引入、\input 路径是否相对主文件书写、公式与表格的编号与交叉引用是否仍指向原位。

报错触发原因处理
! LaTeX Error: Command \foo already defined.命令或环境使用了已存在的名字换名;确认要覆盖时用 \renewcommand
! LaTeX Error: Environment foo undefined.环境定义在被调用之后,或定义所在文件没有被执行到把定义移到导言区,检查 \input 是否被引入
! LaTeX Error: File 'chapters/intro2.tex' not found.\input 路径按当前文件写,而解析以主文件目录为基准改成相对主文件的路径
日志行号与源码对不上命令体或环境体展开后报的位置单独建一个只含定义与调用的小文件编译,定位到具体行

总结

  • 格式收进命令:\newcommand 一次定义,正文反复调用;

  • 结构收进环境:表格、定理框这类骨架用 \newenvironment 封装;

  • 跨文件收进公共文件:\input 摘导言区,\include 拆章节;

  • 先判断再封装:三条标准同时满足才动手。

把主文件和各章节一起导入 EasyLaTeX 编辑器,编译入口按 main.tex 设置。