如何在 \edef 中执行 \scantokens 而不触发“失控定义”

如何在 \edef 中执行 \scantokens 而不触发“失控定义”

我正在尝试找到一种方法来\scantokens在 [等同于] 中使用 e-TeX 命令\edef(好吧,实际上是\xdef,但这可能没有什么实际区别,因为那只是\global的版本\edef)。我这样做的原因是似乎需要回答关于 hyperref 和 pdf outlines 的问题

问题似乎在于,它\scantokens实际上并没有扩展到扫描的标记;它实际上扩展到零,但安排从名为“ ”的伪文件中读取下一个标记,然后将其几乎完全像真实文件一样处理,包括检查“失控”条件。(参见e-TeX 手册

但这个解释有一个问题:为什么\input工作,就像另一个问题中明显出现的那样?

无论如何,这是一个相当简单的例子:

%&eplain

% make \scantokens pseudo-files show up with name " " in the output
\tracingscantokens=1

\edef\foo{\scantokens{Test}}

输出结果

使用“pdftex -interaction=nonstopmode "\input" "scantokens-in-edef-minimal"”在“scantokens-in-edef-minimal”上运行“TeX”
这是 pdfTeX,版本 3.1415926-1.40.11(MiKTeX 2.9)
进入扩展模式
(e:\home\tex\scantokens-in-edef-minimal.tex( )
失控的定义?
->测试
! 扫描 \foo 的定义时文件结束。
<插入文本>
                }
l.6 \edef\foo{\scantokens{测试}
                               }
!} 太多了。
l.6 \edef\foo{\scantokens{测试}}

!紧急停止。
<*> \输入 scantokens-in-edef-minimal

!==> 发生致命错误,未生成输出 PDF 文件!
抄录在 scantokens-in-edef-minimal.log 上。

TeX 于 1 月 27 日星期四 12:24:57 异常退出,代码为 1

是否有可能以某种方式使用宏进行扩展,然后执行\def而不是\edef,这样扩展就会在定义开始之前完成,从而避免“失控定义”的情况?

答案1

简而言之,是的。试试

\edef\foo{\scantokens{Test\noexpand}}

或者

\everyeof={\noexpand}
\edef\foo{\scantokens{text}}

其中,\noexpand通过将 EOF 标记转变为 来“隐藏”它\relax

您可能想看一下 expl3 和 的定义\tl_rescan:nn\tl_set_rescan:Nnn这两个包装器都\scantokens基于 Heiko Oberdiek 包中的想法catchfile

然后你可以写

\tl_set_rescan:Nnn \foo { «catcode setup» } { «rescanned tokens» }

或者

\tl_rescan:nn { «catcode setup» } { «tokens to re-scan (in a group)» }

后者不能在内部使用,\edef但在处理已标记化的宏参数时会派上用场。在实践中,我发现该set_rescan版本更方便一些。

相关内容