\cs_new:Npn \test:n #1
{
\typeout { ==~{ \tl_to_str:n {#1} }~== }
\tl_set:Nn \l_tmpa_tl {#1}
\regex_replace_case_all:nN
{
{ \c{,} } { 111 }
{ \s } { 222 }
}
\l_tmpa_tl
\l_tmpa_tl
}
\def \a {a1\,a2}
%%\typeout: == {XXX:~\a} ==
\test:n { XXX:~\a }
%%\typeout: == {XXX:~\a} ==
\exp_args:No \test:n { XXX:~\a }
%%\typeout: == {XXX:~a1\protect\leavevmode@ifvmode \kern +.1667em\relax a2} ==
\exp_args:Ne \test:n { XXX:~\a }怎样展开才能得到{XXX:~a1\,a2}呢
\exp_args:Ne \test:n { \text_expand:n { XXX: ~\a } }
\exp_args:No 只会把第一个“词元”(token)展开一次,\a 不是第一个词元,所以不会展开。
\, 是 Robust 命令(用 \DeclareRobustCommand 定义的,也就是文档说的 LaTeX-protected),必须使用特定的手段才能保护,在 e 参数里会被直接展开,所以 \exp_args:Ne 不行。
\text_expand:n 会比 e 参数慢很多,一般是临时重定义 \protect,让 Robust 命令生效:
\makeatletter
\let\@@protect\protect
\let\protect\noexpand
\afterassignment\restore@protect
\edef \l_tmpa_tl { XXX: ~\a } % 可以改成 \tl_set:Ne
\exp_args:No \test:n { \l_tmpa_tl }
\makeatother