将 \\ 写入文件

将 \\ 写入文件

我有一个本地类,很多人都在使用。我希望它能做的一件事就是将各种用户定义的数据写入文件,以便后续的 LaTeX 文档可以执行不同的操作,但使用相同的用户定义参数。我对读取和写入外部文件还不太熟悉,所以我的问题可能比较简单。

下面是一个演示该问题的 MWE:

\documentclass{article}
\begin{document}
%% USER CONTROLS THIS DEFINITION
\def\userdef{abc}        % Works Great
%\def\userdef{abc\\def}  % Breaks \write
%% I CONTROL THE FOLLOWING
\def\userdefContent{\noexpand\def\noexpand\userdef{\userdef}}%
\newwrite\tempfile%
\immediate\openout\tempfile=userdata.tex
\immediate\write\tempfile{\userdefContent}
\immediate\closeout\tempfile
\end{document}

用户使用 定义一些已知变量\def,我想将其写入文件,格式为用户定义它的\def\userdef{blah blah blah}位置blah blah blah。这样,我可以\input将其写入另一个文件,并使用用户在第一轮中定义的相同数据对第二个文档进行预初始化。

问题是我想要编写的一些用户变量可能会填充\\字符,这显然会破坏\write。取消注释 MWE 中的一行以演示这一点。

我对解决方案很灵活。理想情况下,我希望我的输出文件包含

\def \userdef {abc\\def}

但我愿意接受

\def \userdef {abc*LINEFEED*def}

其中*LINEFEED*是任意的字符串序列,用于提醒我稍后需要返回\\。作为最后的手段,我甚至会选择

\def \userdef {abc def}

已被剥离的地方\\

我想,如果没有其他解决方案,我会指示用户群不要\\在他们的宏中使用\def我定义的其他宏(然后我可以在之前重新定义它们\write)。但我认为他们可能会反对最后一种方法。我也会反对它,因为它会破坏与旧文档的向后兼容性。

如果有标准的 LaTeX 方式在不同文档之间传输数据,我也愿意接受完全不同的方法。我想补充一点,我有一个stringstings解决方案,当\userdef仅由 catcode 11 和 12 材料和字符组成时\\,它可以工作,但我不能提前保证用户不会在他的 中粘贴其他一些宏\def

答案1

您必须\\在写入时禁用扩展性。但一般来说,\write当允许“自由”输入时会出现问题:\textbf否则类似的命令肯定会中断。

最好构建一个“立即”版本\protected@write

\documentclass{article}
\usepackage{xpatch}
\makeatletter
% get a copy of `\protected@write
\let\protected@iwrite\protected@write
% patch the copy to add \immediate
\xpatchcmd{\protected@iwrite}{\write}{\immediate\write}{}{}
\makeatother

\newwrite\tempfile

\begin{document}
\def\userdef{abc\\def}  % Breaks \write

\immediate\openout\tempfile=userdata.tex
\makeatletter
\protected@iwrite\tempfile{\let\\\relax}{\userdef}
\immediate\closeout\tempfile
\makeatother

\end{document}

请注意\protected@iwrite,与其兄弟一样,它有第二个参数,可以在其中执行声明以更改写入范围的命令含义;在本例中,我将其设置\\为等于,\relax因此它变得不可扩展。如果没有这个,输出将是

abc\protect \\def

临时任务

abc\\def

如预期的。

一种可能的简化方法是使用与 LaTeX 相同的方法\typeout(感谢 David Carlisle 的建议):

\documentclass{article}
\makeatletter
\def\protected@iwrite#1#2#3{%
  \begingroup\set@display@protect
  #2% local assignments
  \immediate\write#1{#3}\endgroup}
\makeatother

\begin{document}
\def\userdef{abc\\\textbf{def}}

\immediate\openout\tempfile=userdata.tex
\makeatletter
\protected@iwrite\tempfile{}{\def\protect\userdef{\userdef}}
\immediate\closeout\tempfile
\makeatother

\end{document}

输出为\def\userdef{abc\\\textbf {def}}。请注意 也是\textbf可以的。\protect当然,脆弱的命令需要 。

相关内容