我有一个 LaTeX 文档,有两个版本,一个短版,一个长版。长版在文档中间插入了一个附加章节。我想要做的是,如果我设置了环境变量,则在相关位置包含附加文件。所以我这样做(在 pdflatex 中):
\documentclass{book}
\usepackage{etoolbox}
\usepackage{catchfile}
\newcommand{\getenv}[2][]{%
\CatchFileEdef{\temp}{"|kpsewhich --var-value #2"}{}%
\if\relax\detokenize{#1}\relax\temp\else\let#1\temp\fi}
\getenv[\INCLUDE]{INCLUDE}
\begin{document}
First paragraph of first file.
Value of the INCLUDE envvar is as follows: \INCLUDE
\ifstrequal{\INCLUDE}{yes}{\input{file2}}{}
Last paragraph of first file.
\end{document}
我知道它可以正确读取环境变量,所以我知道问题出在条件上,但不确定我到底做错了什么。当我使用 INCLUDE=yes 运行此程序时,会打印值 yes,但不会显示 file2 的内容。
(这就像这个问题,但这个问题没有解决环境变量问题。我的环境变量代码来自这个答案,但由于我可以正确打印环境变量,所以我不认为这是问题所在。)
答案1
编辑
改良版
基本上有两个问题:
\ifstrequal
没有扩展其论点- 环境变量的内容末尾有一个空格,表示
yes
将变为yes' '
,因此测试失败。我到现在都找不到原因。
通过使用xstring
package 命令\StrGobbleRight
和\ifdefstring
from etoolbox
package,可以解决这个问题,但愿只是末尾的一个字符需要删除。在输出文档顶部的诊断中可以看到效果,当\temp
和\newtemp
宏输出时——如果删除了空格,环境变量的内容和后面的文本应该会粘在一起。
我重新定义了该getenv
命令,\newgetenv
并使用了扩展\edef\temp
以使该\ifdefstring
命令与文字值一起工作yes
。
\documentclass{book}%
\usepackage{etoolbox}%
\usepackage{xstring}%
\usepackage{catchfile}%
\newcommand{\getenv}[2][]{%
\CatchFileEdef{\temp}{"|kpsewhich --var-value #2"}{}%
\if\relax\detokenize{#1}\relax\temp\else\let#1\temp\fi}
%\getenv[\INCLUDE]{\string INCLUDE}
\def\newtemp{}%
\newcommand{\newgetenv}[2][]{%
\CatchFileEdef{\temp}{"|kpsewhich --var-value #2"}{}%
\StrGobbleRight{\temp}{1}[\newtemp]% Delete the trailing whitespace character
\if\relax\detokenize{#1}\relax\temp\else\edef#1{\newtemp}\fi%
}%
\begin{document}
\newgetenv[\INCLUDE]{INCLUDE}%
%%% Diagnostics:
\temp%
Some Text%
\newtemp%
Some Text%
First paragraph of first file.
Value of the INCLUDE envvar is as follows: \INCLUDE
\ifdefstring{\INCLUDE}{yes}{\input{file2}}{Nothing to do in here}
Last paragraph of first file.
\end{document}
该文件file2.tex
仅包含以下行
\textbf{Hello World}
另一个版本(感谢 H. Oberdiek 的提示)
\endlinechar
可以通过将结尾的空格 ( ) 用作命令\endlinechar=-1\relax
的第三个参数来省略它。这简化了环境变量宏的处理,并且可以删除包\CatchFileEdef
的使用。xstring
\documentclass{book}%
\usepackage{etoolbox}%
\usepackage{catchfile}%
\newcommand{\newgetenv}[2][]{%
\CatchFileEdef{\temp}{"|kpsewhich --var-value #2"}{\endlinechar=-1\relax}%
\if\relax\detokenize{#1}\relax\temp\else\edef#1{\temp}\fi%
}%
\begin{document}
\newgetenv[\INCLUDE]{INCLUDE}%
First paragraph of first file.
Value of the INCLUDE envvar is as follows: \INCLUDE
\ifdefstring{\INCLUDE}{yes}{\input{file2}}{Nothing to do in here}
Last paragraph of first file.
\end{document}
我没有更新屏幕截图,输出中没有任何本质变化。
答案2
另一种不需要 shell 转义的方法。假设您的文件名为file1.tex
。那么您可以按如下方式组织它:
\documentclass{book}
\providecommand{\INCLUDE}[1]{}
\begin{document}
First paragraph of first file.
\INCLUDE{file2}
Last paragraph of first file.
\end{document}
如果你调用 LaTeX 运行
pdflatex "$INCLUDE\input{file1}"
那么,如果你没有INCLUDE
在环境中设置,结果将是\INCLUDE
无效的。另一方面,设置
export INCLUDE='\let\INCLUDE\input'
与之前相同的命令行将输入file2
。
答案3
您正在使用带有章节的书籍类。然后很容易\includeonly
\documentclass{book}
\includeonly{file2,file3}% controlls what will be included
\begin{document}
First paragraph of first file.
\include{file2}
\include{file3}
Last paragraph of first file.
\end{document}
include.cfg
您还可以使用仅包含以下行的外部文件\includeonly{...}
:
\documentclass{book}
\InputIfFileExists{include.cfg}% controlls what will be included
\begin{document}