我编写了一个宏来对字符串的任何部分进行切片。它可以处理普通字符串,但是当传递给它一个用 \newrobustcmd 定义的字符串时,该宏不起作用并导致错误。(如果使用 \DeclareRobustCommand,则没有问题。)我很困惑为什么会发生这种情况? \DeclareRobustCommand 和 \newrobustcmd 都在创建健壮的命令,但是为什么它们的行为不同?
\documentclass{article}
\usepackage{etoolbox}
\def\slice[#1,#2]#3{
\newcount\cwords \cwords=1
\newcount\cstart \cstart=#1
\advance\cstart by -1\relax
\def\sentece{}
\def\empty{}
\edef\tail{#3\space}
\def\extract ##1 ##2;{
\edef\tail{##2}
\ifnum\cwords>\cstart
\ifnum\cwords<#2
\edef\sentece{\sentece\space##1}
\fi
\fi
\advance\cwords by 1\relax
}
\expandafter\extract\tail;
\loop
\expandafter\extract\tail;
\unless\ifx\tail\empty
\repeat
\sentece
}
\begin{document}
% \DeclareRobustCommand\x[1]{This is a test sentece. #1}
% \DeclareRobustCommand\y{\x{end}}
\newrobustcmd\x[1]{This is a test sentece. #1}
\newrobustcmd\y{\x{end}}
\slice[3,5]\y
\end{document}
PS 如何才能充分展开一个健壮的宏?
答案1
它们是完全不同的保护形式,
\DeclareRobustCommand\foo{xxx}
定义\foo
为,\protect\foox
并且它将在中扩展,\edef
除非\protect
在本地定义(例如,到\noexpand
),因此在您的中\edef\tail{#3\space}
它会完全扩展。
第二个定义本质上是
\protected\def\foo{xxx}
使用 e-tex\protected
原语,这定义了不会扩展的命令并且不使用\edef
latex机制。\protect
请注意,\newcount
应该超出您的定义范围,因为您不想在每次使用时分配新的寄存器。此外,所有以}
或结尾的行都{
应该%
避免在输出中生成虚假空格。