对于 TeX 专家来说,这可能很明显,但这里是:
我想创建一个命令,以控制序列(无参数)作为输入并打印该控制序列的名称(不带前导反斜杠)。该怎么做?
答案1
正如一些评论所指出的那样,有各种方法。有几个“尴尬”的情况需要解决:如果转义字符不可打印,以及如果控制序列以空格开头(例如\csname\space awkward\endcsname
)。在expl3
,我们用一个名为的函数来解决这个问题\cs_to_str:N
,在原语中可以写成
\catcode`\@=11 %
\def\cs@to@str{%
\romannumeral\if\string\ \cs@to@str@aux@i\fi
\expandafter\cs@to@str@aux@ii\string
}
\long\def\cs@to@str@aux@i#1\cs@to@str@aux@ii{%
-\number\fi\expandafter\z@
}
\long\def\cs@to@str@aux@ii#1{\z@}
并用作
\cs@to@str\foo % => "foo"
\expandafter\cs@to@str\csname\space foo\endcsname % => " foo"
为了解释其工作原理,有三种情况
转义符是可打印的,而不是空格。在本例中,
\string\
给出了两个标记(转义符和空格),它们具有不同的 catcode。\if
因此测试为假,因此\string
可以安全地使用第二个标记,但要\cs@to@str@aux@ii
删除转义符。转义符不可打印。在这种情况下,
\string\
仅产生一个标记,测试继续,扩展\cs@to@str@aux@i
。插入-
强制测试为假,\string
可直接用于给出所需的输出。转义符是一个空格。在本例中,
\if
测试为真,并\cs@to@str@aux@i
导致插入 ,-\z@
其\number
变为-0
。这并非“终止”,因此 会\romannumeral
寻找可选空格。它在转义符中找到了它,因此将其删除,只留下控制序列名称。
在这三种情况下,请注意,我们永远无法从名称本身删除前导空格,因为我们永远不会删除非转义字符的标记。
由于这一切都是内置的expl3
,我只需创建一个文档级别名:
\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\newcommand{\CsToStr}[1]{\cs_to_str:N #1}
\ExplSyntaxOff
\begin{document}
\CsToStr{\LaTeX}
\CsToStr{\def}
\CsToStr{\newcommand}
\CsToStr{\MacroName}
\end{document}
xparse
(当然,您可以使用 来做到这一点)。
答案2
您还可以使用该xstring
包以及\string
:
代码:
\documentclass{article}
\usepackage{xstring}
\newcommand*{\MacroName}[1]{\StrGobbleLeft{\string#1}{1}}%
\begin{document}
\MacroName{\LaTeX}
\MacroName{\def}
\MacroName{\newcommand}
\MacroName{\MacroName}
\end{document}