我定义了一个宏\test
,如下:
\usepackage{xstring}
\newcommand{\test}[1]{
\StrGobbleRight{#1}{1}[\temp]
\expandafter\newcommand\csname\temp\endcsname{Name: \temp}
}
它用其参数的名称创建一个新的宏,然后将这个名称存储在这个新宏中(我创建这个宏只是为了说明我的问题,并不是说我真的需要这个宏的功能)。因此,
\test{aaa}
\aaa
会得到Name: aaa
。但是,如果在这之后有一个\test{bbb}
,则\aaa
变成Name: bbb
,因为\aaa
存储的是宏\temp
,而不是它的值。
我希望保持aaa
一个常数的值。为此,我\expandafter
之前尝试添加\temp
,但没有成功。正确的方法是什么?
\newcommand
(我知道我可以将这个例子中的第二个改为来\edef
解决这个问题。但如果我使用,这将不起作用\newtheorem
。我真正想知道的是如何获得价值的\temp
。)
下面是 MWE。
\documentclass{article}
\usepackage{xstring}
\newcommand{\test}[1]{
\StrGobbleRight{#1}{0}[\temp]
\expandafter\newcommand\csname\temp\endcsname{Name: \temp}
}
\begin{document}
\test{aaa}
\aaa
\test{bbb}
\aaa
\end{document}
答案1
您必须\edef
使用\def
:
\def\test#1{%
\def\temp{#1}% It emulates your \StrGobble
\expandafter\edef\csname#1\endcsname{Name: \temp}
}
或者更直接一点:
\def\test#1{\expandafter\def\csname#1\endcsname{Name: #1}}
编辑好的,当您使用时\newtheorem
,您的工作就更多了。(我从不使用诸如\newcommand
或 之类的东西\newtheorem
,只使用\def
、\edef
、\gdef
、\xdef
,因此,我使用 TeX 的生活更简单)。
您可以使用\edef\tempi
三个\expandafter
:
\def\test#1{%
\def\temp{#1}%
\edef\tempi{name: \temp}%
\expandafter\newtheorem\expandafter\temp\expandafter{\tempi}%
}
答案2
您可以使用 来完成此操作xstring
,但使用 更简单expl3
:
\documentclass{article}
\ExplSyntaxOn
\NewDocumentCommand{\test}{O{0}m}
{
\jinwen_test:nn { #1 } { #2 }
}
\cs_new_protected:Nn \jinwen_test:nn
{% #1 = how many characters to gobble from the right
% #2 = string
\cs_new:cpx { #2 } { Name: ~ \tl_range:nnn { #2 } { 1 } { - 1 - #1 } }
}
\ExplSyntaxOff
\frenchspacing
\begin{document}
\test{aaa}
\test[3]{abcdef}
\texttt{\meaning\aaa}
\texttt{\meaning\abcdef}
\end{document}
您xstring
可以使用参数交换技术来避免\edef
。
\documentclass{article}
\usepackage{xstring}
\makeatletter
\newcommand{\test}[2][0]{%
\StrGobbleRight{#2}{#1}[\jinwen@temp]
\expandafter\jinwen@makecommand\expandafter{\jinwen@temp}{#2}%
}
\newcommand{\jinwen@makecommand}[2]{%
\expandafter\newcommand\csname#2\endcsname{Name: #1}%
}
\makeatother
\frenchspacing
\begin{document}
\test{aaa}
\test[3]{abcdef}
\texttt{\meaning\aaa}
\texttt{\meaning\abcdef}
\end{document}
答案3
只要所讨论的字符串不包含哈希值(),\temp
定义临时宏的方法就可以起作用。\StrGobbleRight
#
您可以将顶层扩展\temp
作为另一个执行实际工作的宏的参数:
\documentclass{article}
\usepackage{xstring}
\newcommand{\test}[1]{%
\begingroup
\StrGobbleRight{#1}{1}[\temp]%
\expandafter\endgroup\expandafter\innertest\expandafter{\temp}%
}%
\newcommand\innertest[1]{%
\expandafter\newcommand\csname#1\endcsname{Name: #1}%
}%
\begin{document}
\test{aaax}
\test{bbbx}
\texttt{\string\aaa:\meaning\aaa}
\texttt{\string\bbb:\meaning\bbb}
\end{document}
如果允许 ε-TeX 扩展,您可以使用\protected@edef
并包装所有内容,但\temp
实际上\unexpanded
在这个例子中\unexpanded
不需要,因为字符Name:
不可扩展,但可能有类似的东西\newtheorem
:
\documentclass{article}
\usepackage{xstring}
\makeatletter
\newcommand{\test}[1]{%
\StrGobbleRight{#1}{1}[\temp]%
\expandafter\@ifdefinable\csname\temp\endcsname{%
\expandafter\protected@edef\csname\temp\endcsname{\unexpanded{Name: }\temp}%
}%
}%
\makeatother
\begin{document}
\test{aaax}
\test{bbbx}
\texttt{\string\aaa:\meaning\aaa}
\texttt{\string\bbb:\meaning\bbb}
\end{document}
如果您喜欢复杂的东西,您可以在ing 标记\expandafter
之前应用。 您可以使用它来保持扩展,直到找到非正数。 (默默地丢弃非正数而不提供任何标记作为回报。)\Exchange
\romannumeral
\romannumeral
使用下面的示例来\Stopromannumeral
表示数字0
,其中您不会不必要地删除尾随空格标记,并且不0
涉及可能受 / 影响\uppercase
/更改的显式字符标记\lowercase
。
在的\expandafter
扩展过程中启动的 -chain 启动了-expansion 。反过来又触发了-token后面的两个的扩展,这又产生了 的顶层扩展。 然后触发。 之后\csname
\romannumeral
\romannumeral
\expandafter
\romannumeral
\temp
\romannumeral
\Exchange
\Stopromannumeral
,即 TeX-⟨数字⟩- 发现数量为“0”的值,结尾\romannumeral
为\romannumeral
形成该标记的标记⟨数字⟩-数量,但不提供代币作为回报。
\documentclass{article}
\usepackage{xstring}
\makeatletter
\newcommand\Exchange[2]{#2#1}%
\@ifdefinable\Stopromannumeral{\chardef\Stopromannumeral=`\^^00}%
\makeatother
\newcommand{\test}[1]{%
\StrGobbleRight{#1}{1}[\temp]%
\expandafter\newcommand
\csname\temp\expandafter\endcsname
\expandafter{%
\romannumeral
\expandafter\Exchange\expandafter{\temp}{\Stopromannumeral Name: }%
}%
}%
\begin{document}
\test{aaax}
\test{bbbx}
\texttt{\string\aaa:\meaning\aaa}
\texttt{\string\bbb:\meaning\bbb}
\end{document}