将命令行参数传递给LaTeX文档

56
有时候,我会定义像下面这样的新命令。
\newcommand{\comment}[1]{\textbf{#1}}
%\necommand{\comment}[1]{\emph{#1}} 
上述命令使我能够一次性更改代码的部分样式。如果我想生成两种可能的样式,我必须每次编译我的LaTeX文档两次,每次修改源代码以启用所需的样式。
在这种情况下,有没有办法避免源代码的修改?也就是说,我可以通过传递一些命令行参数来选择要使用哪种样式吗?

1
请参阅 tex.SX 上的 将参数传递给文档 - fbmd
请查看Pandoc模板。它支持在命令或文件中指定键:-M KEY[=VAL], --metadata=KEY[:VAL] - AvidSeeker
4个回答

79

也就是说,我能否向LaTeX传递一些命令行参数,以便可以基于那些参数选择使用哪种样式?

可以。有三种选项:

第一种方式

在你的源文件中写入

\providecommand{\comment}[1]{\emph{#1}}% fallback definition

然后将 LaTeX 文档("myfile.tex")编译为:

pdflatex (whatever options you need) "\newcommand\comment[1]{\textbf{#1}}\input{myfile}"

或者,

pdflatex "\let\ifmyflag\iftrue\input{myfile}"

然后在源代码中添加

\ifcsname ifmyflag\endcsname\else
  \expandafter\let\csname ifmyflag\expandafter\endcsname
                  \csname iffalse\endcsname
\fi
...
\ifmyflag
  \newcommand\comment[1]{\emph{#1}}
\else
  \newcommand\comment[1]{\textbf{#1}}
\fi

或者甚至更多

pdflatex "\def\myflag{}\input{myfile}"

使用

\ifdefined\myflag
  \newcommand\comment[1]{\emph{#1}}
\else
  \newcommand\comment[1]{\textbf{#1}}
\fi

这可能是最短的方法,尽管稍微有点脆弱,因为你永远不知道某个软件包是否会在背后定义\myflag


你能用“latex”做类似的技巧吗?还是这些技巧只适用于“pdflatex”? - reprogrammer
1
你能详细说明第二个选项中以\ifcsname开头的代码是做什么的吗? - Faheem Mitha
1
我很喜欢你的回答。有没有办法在latexmk中使用这种方法? - kuszi
3
使用latexmk,可以像这样工作:latexmk -pdf -pdflatex='pdflatex -interaction=nonstopmode -shell-escape "\newcommand{\pdfTitle}{MyTitle}\include{filename}"' filename.tex。另请参见:向文档传递参数 - Sr. Schneider

5

当您需要相对灵活的一次性选项时,例如更改简历上的位置线时,应使用Will的方法。但是,如果您一遍又一遍地生成相同的选项,则应考虑避免命令行参数,或将其纳入构建脚本或makefile中。

以下是两种避免命令行参数的技巧:

技巧1:如果您正在生成必须保持可访问的固定文档数组(例如您的两个样式示例),则我建议在另一个tex文件中实现Will的latex代码,即thesis.tex包含\providecommand\comment[1]{\emph{#1}},而thesis-ugly.tex由\newcommand\comment[1]{\textbf{#1}} \input thesis.tex组成。

当使用此技术时,当然需要重新运行诸如bibtex之类的工具,除非您为中间文件创建符号链接,例如ln -s thesis.aux thesis-ugly.auxln -s thesis.bbl thesis-ugly.bbl

技巧2:我发现对于更改文档纸张大小,技巧1有些棘手,因此我编写了以下perl脚本,简称为papersize。命令papersize A4 teaching.tex会直接修改teaching.tex,并将teaching.pdf链接到teaching-A4.pdf,因此运行pdflatex teaching会创建teaching-A4.pdf,但不会干扰现有的teaching-letter.pdf,并且不需要重新运行bibtex teaching。 显然,对于具有内部引用的文档,它需要重新运行两次pdflatex。

#!/usr/bin/perl -i~ -n

BEGIN {
die "Usage: papersize letter/A4/etc. [filename]\n" if ($#ARGV < 0);
$SIZE = shift @ARGV;  @files=@ARGV;
$FLAG = "% paper size :: ";
}

if (/$FLAG(\w+)/) {
    if ($1 eq $SIZE) {
        s/^\% //;
    } else {
        s/^([^\%])/\% \1/;
    }
}
print $_;

END {
foreach (@files) {
    if (s/\.tex//) {
    $l = "$_-$SIZE.pdf";  $_ .= ".pdf";
    unlink($_) if (-l $_);
    symlink($l,$_) if (! -e $_);
} }
}

当您更改纸张大小时,必须向每个需要更改的文件行添加特殊注释% paper size :: ...

\documentclass[letterpaper,11pt]{article}  % paper size :: letter
% \documentclass[a4paper,11pt]{article}  % paper size :: A4
\usepackage[text={6.5in,8.8in}]{geometry}  % paper size :: letter
% \usepackage[text={16.4cm,24.5cm}]{geometry}  % paper size :: A4

您可以将纸张大小显然地加入构建脚本或 makefile 中,或者修改上述脚本以用于 .dvi 文件。或将脚本推广到其他修改。


1

这可能不是针对该情况的最佳解决方案(也是一篇非常古老的文章),但我认为我可以提供一个对我有用的替代方案。简单来说,就是将两个命令定义在两个不同的文件中,将第三个文件链接到所需的选择,并\input该第三个文件。 例如,定义:

% in main.tex
\input{options}
% ...

.

% in option1.tex
\newcommand{\comment}[1]{\textbf{#1}}

.

% in option2.tex
\newcommand{\comment}[1]{\emph{#1}} 

然后使用选项1进行编译,只需运行:

> ln -s option1.tex options.tex && pdflatex main.tex

我更喜欢这种方式,因为我比较熟悉bash而不是晦涩的latex,对于文件的增多也没有问题(可以轻松地将它们组织在子目录中),并且我的脚本会编译文档,所以这个额外的步骤几乎没有成本。

这样做会创建竞态条件,您必须注意不要同时运行这些shell函数。当然,可以添加一些锁定,但那将变得过于复杂。无论如何,这是一个有趣的工作流程。 - HappyFace

0
为了提供既符合要求的格式,又不浪费纸张的紧凑版版本的论文,我使用了 ifthen,以及 makesed 的一些奇技淫巧来重写页眉。
我认为威尔的方法都比较好。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接