我在更改 catcode 的环境中工作,需要重新扫描标记才能继续处理文本。但是,我遇到了问题。即使使用这个最低限度的代码,我仍然遇到问题。
\documentclass{article}
\makeatletter
\newcommand\aeinput[1]{%%
\begingroup
\scantokens{\gdef\ae@input{::#1::}}%%
\endgroup
\ae@input
}%%
\makeatother
\begin{document}
\aeinput{HELLO}
\end{document}
导致错误:
! Undefined control sequence.
\aeinput ...ae@input {::#1::}}\endgroup \ae@input
如果我写:我会得到同样的错误:
\scantokens{\xdef\ae@input{::#1::}}%%
为什么这不能编译?
另外,如果我做类似的事情
\expandafter\gdef\expandafter\ae@input\expandafter{\scantokens{::#1::}}%%
我收到以下错误:
! File ended while scanning definition of \ae@input.
即使添加也\everyoef{\noexpand}
无济于事。
然而,以下确实有效(这让我更加困惑)。
\xdef\ae@input{\scantokens{::#1::}}%%
那么,这里发生了什么事?
这个问题从何而来?
我以为我有一个简单的答案在已经更改 catcode 的环境中输入文本.
基本上,在这个问题中我有一个环境
\begin{speech}
inside here periods have a different catcode
\end{speech}
这个问题的原作者想做类似的事情
\begin{speech}
\input{text.tex}
\end{speech}
显然,\input
在这里不起作用,因为.
catcode 错误。我以为我可以\input{text.tex}
通过执行以下操作轻松解决这个问题(并允许 OP 继续写入),例如
\makeatletter
\newcommand\aeinput[1]{%%
\begingroup
\catcode`\.=\periodcatcode
\scantokens{\gdef\ae@input{\input{#1}}}%%
\endgroup
\ae@input
}%%
\makeatother
另一种方法是
\makeatletter
\newcommand\aeinput[1]{%%
\begingroup
\catcode`\.=\periodcatcode
\scantokens{\gdef\ae@filehandle{#1}}%%
\endgroup
\input{\ae@filehandle}%%
}%%
\makeatother
这样,输入文件将根据speech
环境适当地处理周期。
就像是
\newcommand\aeinput[1]{%%
\begingroup
\catcode`\.=\periodcatcode
\scantokens{\input{#1}}%%
\endgroup
}
仅从表面上看它可以工作,但输入文件将不再具有句点的正确 catcode。
答案1
请记住,\scantokens
类别代码有效当它被使用时.因此在
\documentclass{article}
\makeatletter
\newcommand\aeinput[1]{%%
\begingroup
\scantokens{\gdef\ae@input{::#1::}}%%
\endgroup
\ae@input
}%%
\makeatother
\begin{document}
\aeinput{HELLO}
\end{document}
\scantokens
文档中插入了一行,其中不是@
字母。因此
\gdef\ae@input
将其定义\ae
为宏,后面跟着@input
替换文本::<#1>::
。您需要更改组内的类别代码
\documentclass{article}
\makeatletter
\newcommand\aeinput[1]{%%
\begingroup
\makeatletter
\scantokens{\gdef\ae@input{::#1::}}%%
\endgroup
\ae@input
}%%
\makeatother
\begin{document}
\aeinput{HELLO}
\end{document}
正如您所观察到的,虽然\scantokens
是可扩展的,但要做到这一点有点棘手,因为它使用的虚拟文件的“文件结尾”有些奇怪。这些可以解决(参见代码\tl_rescan:nn
和 中的类似代码expl3
),但这并不简单。