例如,我想包含一个图形:~/figures/figure.pdf
。在我的 Linux 机器上,这是/home/me/figures/figure.pdf
,但在 OS X 上是/Users/me/figures/figure.pdf
。如果有一个环境变量,我希望它能这样$HOME
,以便 latex 文件可以在两台机器上编译\includegraphics{$HOME/figures/figure.pdf}
。(当然它不会使用符号$
)。
我刚刚发现这个帖子但是 write18 是最原生的方式吗?而且,在给定的例子中,赋值实际上不会在 LaTex 中定义变量。我试过了
\immediate\write18{echo "\newcommand{\HOME}{$HOME}" > var.tex}
但给了我这个错误:
! Argument of \@gobble has an extra }.
所以现在我很茫然。
答案1
如果您有最新的 TeX Live(2010 或更高版本)或 MiKTeX(v. 2.9),那么以下操作可以起作用(并且不需要-shell-escape
命令行选项):
\usepackage{catchfile}
\newcommand{\getenv}[2][]{%
\CatchFileEdef{\temp}{"|kpsewhich --var-value #2"}{\endlinechar=-1}%
\if\relax\detokenize{#1}\relax\temp\else\let#1\temp\fi}
\getenv[\HOME]{HOME}
如果您只说,\getenv{VAR}
那么变量的值就会被打印出来,而不是存储在控制序列中。
不仅HOME
可以使用,还可以使用任何环境变量以及 TeXkpathsea
系统中定义的“伪变量”,例如TEXMF
或TEXINPUTS
。
请注意,这是有效的仅有的使用pdflatex
。使用其他引擎或较旧的发行版,需要 shell escape。当然 LuaTeX 有其与系统交互的方法。
适用于所有最近的引擎是
\documentclass{article}
\usepackage{ifxetex,ifluatex}
\ifxetex
\usepackage{catchfile}
\newcommand\getenv[2][]{%
\immediate\write18{kpsewhich --var-value #2 > \jobname.tmp}%
\CatchFileDef{\temp}{\jobname.tmp}{\endlinechar=-1}%
\if\relax\detokenize{#1}\relax\temp\else\let#1\temp\fi}
\else
\ifluatex
\newcommand\getenv[2][]{%
\edef\temp{\directlua{tex.sprint(
kpse.var_value("\luatexluaescapestring{#2}") or "" ) }}%
\if\relax\detokenize{#1}\relax\temp\else\let#1\temp\fi}
\else
\usepackage{catchfile}
\newcommand{\getenv}[2][]{%
\CatchFileEdef{\temp}{"|kpsewhich --var-value #2"}{\endlinechar=-1}%
\if\relax\detokenize{#1}\relax\temp\else\let#1\temp\fi}
\fi
\fi
\begin{document}
\getenv[\HOME]{HOME}\show\HOME
\end{document}
xetex
在辅助文件\jobname.tmp
被写入的情况下并且-shell-escape
是必要的。
注意:LuaTeX 方法由 Patrick Gundlach 建议。如果变量未设置或未知kpathsea
,则结果将为空字符串。
2019 年更新
使用最新版的 TeX 发行版,以下内容适用于所有引擎(当然,Knuth TeX 除外):、 、 和pdflatex
。xelatex
无需lualatex
无限制的 shell 转义。platex
uplatex
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\getenv}{om}
{
\sys_get_shell:nnN { kpsewhich ~ --var-value ~ #2 } { } \l_tmpa_tl
\tl_trim_spaces:N \l_tmpa_tl
\IfNoValueTF { #1 }
{
\tl_use:N \l_tmpa_tl
}
{
\tl_set_eq:NN #1 \l_tmpa_tl
}
}
\ExplSyntaxOff
\begin{document}
\getenv[\HOME]{HOME}\show\HOME
\end{document}
答案2
@egreg 已经回答了你的问题,所以我想我不会回答。建议不要依赖环境变量。如果 latex 文件只是\includegraphics{figures/figure.pdf}
然后,如果$HOME/figures//
在 TEXINPUTS 环境变量或texmf.cnf
配置设置中,则无需 LaTeX 明确访问机器特定信息即可找到该文件。这会将机器特定信息和目录结构保留在 kpathsearch 系统中,该系统经过优化以处理此类问题,而不是尽可能避免此类问题的宏层。
此外,对于主目录的特定情况,您可以(在至少 linux 和 windows/cygwin 上的 web2c 系统上,但我认为其他系统也是如此)使用\string~/figures/figure.pdf
kpathsea 理解~
的主目录(但您必须向其传递一个文字,~
而不是不可破坏空间的正常活动定义,因此\string
.
答案3
@egreg 针对新版本更新的答案对我来说不起作用,但是这样做:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\getenv}{om}
{
\sys_get_shell:nnN{ kpsewhich ~ --var-value ~ #2 }{}#1
}
\ExplSyntaxOff
\begin{document}
\getenv[\HOME]{HOME}
\HOME
\end{document}
我不知道这是否是预期的行为,但它对我有用,并且根据文档,\sys_get_shell:nnN
它似乎是预期的行为。