\write 中带有可选参数的命令

\write 中带有可选参数的命令

为了以安全且可控的方式从大型 LaTeX 文件中提取文本,我让 LaTeX 本身写入文本文件。为了保留和调整一些格式信息和结构元素,我为文件提供了一个新标题,并在其中重新定义了用于此特殊目的的命令。这很好用,直到我需要带有可选参数的命令为止。

newfile为了方便使用:

\documentclass{minimal}

\usepackage{newfile}
\newoutputstream{out}
\openoutputfile{out.text}{out}


\newcommand{\standardexample}[3]{#1:#2(#3)}
\newcommand{\optionalexample}[3][default]{#1:#2(#3)}

\begin{document}

text \standardexample{1}{2}{3} and \optionalexample[not default]{2}{3} or \optionalexample{2}{3}

\addtostream{out}{
text \standardexample{1}{2}{3} and \optionalexample[not default]{2}{3} or \optionalexample{2}{3}
}

\closeoutputstream{out}

\end{document}

我明白了

text 1:2(3) 而不是 default:2(3) 或 default:2(3)

在 pdf 中如预期的那样,但是

text 1:2(3) 和 \optionalexample[非默认]{2}{3} 或 \optionalexample{2}{3}

在文本文件中,日志中没有错误。

测试不使用newfile,例如

\documentclass{minimal}

\newcommand{\standardexample}[3]{#1:#2(#3)}
\newcommand{\optionalexample}[3][default]{#1:#2(#3)}


\newwrite\tempfile

\begin{document}
\immediate\openout\tempfile=\jobname.tmp
\immediate\write\tempfile{text \standardexample{1}{2}{3} and \optionalexample[not default]{2}{3} or \optionalexample{2}{3}}
\immediate\closeout\tempfile


text \standardexample{1}{2}{3} and \optionalexample[not default]{2}{3} or \optionalexample{2}{3}


\end{document}

排版被一些错误消息打断了(其中一些甚至包含在 tmp 文件中),但我真的无法理解它们。

无论是扩展还是解决方法都很好。

答案1

使用可选参数定义的命令会自动增强,但这意味着它们能够存活下来\protected@write;它们肯定不会\write因为保护机制而存活下来。

这主要取决于你想写入辅助文件的内容;如果你需要扩张对于这些命令,您就没那么幸运了,因为它们必须执行分配才能生成替换文本。

使用\protected@write如下输入

\protected@write\tempfile{}{\optionalexample[not default]{2}{3} or \optionalexample{2}{3}}

会写

text \optionalexample [not default]{2}{3} or \optionalexample {2}{3}

您可以\immediate在以下位置找到版本将 \\ 写入文件

如果您需要命令的完整扩展,您可以使用xparse

\usepackage{xparse}
\DeclareExpandableDocumentCommand{\optionalexample}{O{default}mm}{#1:#2(#3)}

并且这将在 中起作用\immediate\write


\newcommand您可以找到一些关于使用以下方法定义的带有可选参数的宏的讨论\newcommand[.][.]{.} 定义的命令是否强大?

你可以看到,\optionalexample当 TeX 扩展你的宏时,它变成了

\@protected@testopt \optionalexample \\optionalexample {default}

现在问题开始了:当你执行 时,的\immediate\write值为(这反过来意味着,但这并不相关。这是 的定义:\protect\@typeset@protect\relax\@protected@testopt

% latex.ltx, line 619:
\def\@protected@testopt#1{%%
  \ifx\protect\@typeset@protect
    \expandafter\@testopt
  \else
    \@x@protect#1%
  \fi}

在这种情况下,条件返回 true,因此 TeX 将显示

\@testopt \optionalexample \\optionalexample {default}

做什么\@testopt?如下:

% latex.ltx, line 617:
\long\def\@testopt#1#2{%
  \kernel@ifnextchar[{#1}{#1[{#2}]}}

这就是罪魁祸首!在\write宏扩展期间,只执行宏扩展,而不执行赋值,因此\kernel@ifnextchar无法工作,因为它是\futurelet为了扫描以下标记而执行的。

相关内容