如何将字符串连接成单个命令?

如何将字符串连接成单个命令?

我想将数学文本的几个部分连接成一个命令,我读到了一个很好的解决方案这里在这个网站上,允许我创建这个工作示例来表达我的意思:

\documentclass[a4paper,10pt]{report}
\usepackage[francais]{babel}

\def\reptemp{I love rain}
\global\edef\reptemp{\reptemp, but not too much.}

\begin{document}
\reptemp
\end{document} 

不幸的是,由于某种原因,它拒绝处理更复杂的东西,例如

\documentclass[a4paper,10pt]{report}
\usepackage[francais]{babel}

\def\reptemp{I {\it love} rain}
\global\edef\reptemp{\reptemp, but \bf{not} too much.}

\begin{document}
\reptemp
\end{document} 

产生以下错误信息

! Missing control sequence inserted.
<inserted text> 
                \inaccessible 
l.16 \reptemp
?

当然,我想通过这种方法连接复杂的东西(环境、枚举等),我想知道这是否可行。

答案1

您想要实现的目标可以通过多种方式实现。首先,让我从一个小提示开始:命令\bfit已经过时,并且它们没有参数。请参阅此答案:尽管使用反斜杠美元符号,错误仍然存​​在


首先,您必须决定是否将内容保存在令牌列表寄存器中或命令中。Joseph Wright 的出色回答很好地解释了这些差异以及对您的问题的一些解释。 \toks 是否需要定义 \g@addto@macro?一般可以避免使用令牌寄存器吗?


使用命令:

方法 1:使用\g@addto@macro

\g@addto@macro在 LaTeX 内核中定义。根据受保护的符号,@您必须使用\makeatletter... \makeatother,请参阅:\makeatletter 和 \makeatother 起什么作用?

\documentclass[a4paper,10pt]{report}
\makeatletter
\def\reptemp{I \textit{love} rain}
\g@addto@macro\reptemp{, but \textbf{not} too much.}
\makeatother
\begin{document}
\reptemp
\end{document} 

方法 2:使用包etoolbox

该包etoolbox定义了一些辅助宏,用于向给定命令添加新信息。可以在命令之前和之后添加材料。Egreg 提供了具有相同功能的更强大的包。该包称为xpatch。他还提供了一个更强大的包,声明为实验版本,包regexpatch

下面是一个例子etoolbox

\documentclass[a4paper,10pt]{report}
\usepackage{etoolbox}
\def\reptemp{I \textit{love} rain}
\appto\reptemp{, but \textbf{not} too much.}
\begin{document}
\reptemp
\end{document} 

该软件包etoolbox提供了更多有用的功能,并且也可以加载xpatch


一种特殊而新颖的现代方法是使用 LaTeX3 项目和语言的宏expl3。在这里,您可以使用标记寄存器以及序列。范围真的很大。新语法的使用需要一些特殊处理,这在简短手册中有说明expl3。当然,您会在 tex.stackexchange 上找到很多相关问题。

答案2

这只是对 Marco Daniel 的精彩回答的一个补充。

如果我们只需要将以下内容\edef追加(或添加,或两者兼而有之)到一串人物。它可以与其他代币一起使用,但我们将其限制在一个简单的应用程序中:

\def\mystring{} % initialize
\def\extendmystring#1#2{\edef\mystring{#1\mystring#2}}

然后

\extendmystring{I love rain}{}
\extendmystring{}{, but not too much.}
\extendmystring{``}{''}

会导致\mystring扩展为

``I love rain, but not too much.''

然而这是不是如果你想保留结构我们存储的内容

该命令(在您的示例中\textit应该使用它来代替)\it扩展进入说服 TeX 以斜体打印参数所需的说明。即使\textit保留了\edef,您也会丢失一些信息。

让我们看一个与 一起工作的示例\edef。代码

\def\mand#1#2{#1 and #2} % "macro and"
\def\mystring{I love \mand{rain}{snow}} % reinitialize
\extendmystring{``}{, but not too much.''}

将导致\mystring扩展为

``I love rain and snow, but not too much.''

而“rain”和“snow”作为参数的信息则\mand完全丢失。在实际应用中,人们可能依赖于\mand替换文本和重新定义在扩展(使用)之前\mystring;如果\mand保留,那么很容易说

\def\mand#1#2{#2}

并使用\mystring将打印

“我喜欢雪,但不是太喜欢。”

同时保持信息完整\mystring。这惯于使用该\edef技术。

问题在于,它将\edef宏(准确地说是可扩展标记)一直扩展为不可扩展标记。像\textit(以及过时的\it)这样的宏无法生存\edef原因很难用几句话解释清楚。

如果你想保存信息,那么\preto\appto路肯定更好。

答案3

这将起作用:

\documentclass{report}

\def\reptemp{I {\itshape love} rain}
\expandafter\def\expandafter\reptemp\expandafter{\reptemp, but {\bfseries not} too much.}

\begin{document}
\reptemp
\end{document} 

它首先扩展旧的定义,\reptemp然后定义新的定义

答案4

\reptemp需要扩展宏以将标记添加到其替换文本中。

因此连续哈希的数量减半:

\def\reptemp{Some hashes: ########}
\show\reptemp
\expandafter\edef\expandafter\reptemp\expandafter{\reptemp, 1}
\show\reptemp
\expandafter\edef\expandafter\reptemp\expandafter{\reptemp, 2}
\show\reptemp
% The following yields: "! Illegal parameter number in definition of \reptemp."
%\expandafter\edef\expandafter\reptemp\expandafter{\reptemp, 3}
%\show\reptemp
\stop

(这里使用了。使用 //时\edef哈希值也会减半。)\def\gdef\xdef

为了防止这种情况,你可以将内容包装到\unexpanded

\newcommand\extendmystringmacro[3]{%
  \edef#1{\unexpanded{#2}\unexpanded\expandafter{#1#3}}%
}%
\def\reptemp{I \textit{love} rain}
\show\reptemp
\begingroup
\extendmystringmacro{\reptemp}{}{, but \textbf{not} too much.}
\show\reptemp
\extendmystringmacro{\reptemp}{}{ Some hashes:  ########}
\show\reptemp
\extendmystringmacro{\reptemp}{A, }{, 1}
\show\reptemp
\extendmystringmacro{\reptemp}{B, }{, 2}
\show\reptemp
\global\extendmystringmacro{\reptemp}{C, }{, 3}
\endgroup
\show\reptemp
\stop

...或者进入令牌寄存器但以\globaletc 作为前缀则不起作用:

\makeatletter
\newcommand\exchange[2]{#2#1}%
\newcommand\extendmystringmacro[3]{%
  \expandafter\exchange\expandafter{%
    \expandafter\toks@\expandafter{\the\toks@}%
  }{%
    \toks@{#2}%
    \toks@\expandafter{\the\expandafter\toks@#1#3}%
    \edef#1{\the\toks@}%
  }%
}%
\makeatother
\def\reptemp{I \textit{love} rain}
\show\reptemp
\extendmystringmacro{\reptemp}{}{, but \textbf{not} too much.}
\show\reptemp
\extendmystringmacro{\reptemp}{}{ Some hashes: ########}
\show\reptemp
\extendmystringmacro{\reptemp}{A, }{, 1}
\show\reptemp
\extendmystringmacro{\reptemp}{B, }{, 2}
\show\reptemp
\extendmystringmacro{\reptemp}{C, }{, 3}
\show\reptemp
\stop

(对于我的所有示例,都没有进行检查以检测的\extendmystringmacro第一个参数是否确实由单个标记组成,该标记表示不处理参数的宏。)

相关内容