\CatchFileDef 与 ( \input 或 \@@input )

\CatchFileDef 与 ( \input 或 \@@input )

我发现了 catchfile这里 现在我想了解这个包是如何工作的。下面是一些使用\foreach或的测试\@for

\documentclass{article}
\usepackage{filecontents,catchfile,pgffor}

\begin{document}

\def\mylist{1,2,3,4} 
Test 1:\foreach \i in \mylist {\hspace{\i cm}\i} 

\begin{filecontents*}{mylist.dat}
1,2,3,4
\end{filecontents*}

\CatchFileDef{\tempa}{mylist.dat}{}% 

Test 2:\foreach \i in \tempa{\hspace{\i cm}\i} 

\makeatletter 

Test 3:\@for\i:=\tempa\do{\hspace{\i cm}\i}

\def\tempb{\@@input mylist.dat } 

% I know this is not the right way but I always find it difficult to explain


Test 4: this is the content : \tempb  
% \foreach \i in \tempb 
% {\hspace{\i cm}\i}    %  

Test 5:\@for\i:=\tempb\do{\hspace{\i cm}\i} 

\begin{filecontents*}{myfile.dat}
\def\tempc{1,2,3,4}
\end{filecontents*}  
\input{myfile.dat}

% last try ! and it works
Test 6:\foreach \i in \tempc{\hspace{\i cm}\i}   

\end{document}

A) 测试 4 不起作用。但为什么测试 2 可以\CatchFileDef工作?对这类问题有一个清晰的解释会很有趣!

B)现在为什么测试 6 有效?

答案1

的定义\CatchFileEdef可以简化为

\newcommand\easyCatchFileEdef[3]{%
   \begingroup\everyeof{\noexpand}%
   #3\relax
   \xdef\@temp{\@@input #2\space}%
   \endgroup
   \let#1\@temp
}

但 Heiko Oberdiek 还添加了许多检查。 是\everyeof{\noexpand}必要的,以消除 TeX 添加到其输入的每个文件中的隐式空行。\@@input命令是原始的\input,它是可扩展的(使用空扩展); 最后一个\space用于应对 TeX 关于 (原始)的惯例\input:查找并忽略空格。 第三个参数用于在输入文件时添加设置,例如\endlinedchar

一切都\xdef扩展了(它的\global\edef),但只是#1在本地定义。

更复杂的是\CatchFileDef,因为人们只想扩展\@@input而不是实际输入的内容。未删节的版本是

\makeatletter
\def\easyCatchFileDef#1#2#3{%
  \begingroup\everyeof\expandafter{\CatchFileEOF\expandafter\CatchFileFinish\noexpand}%
  \expandafter\long\expandafter\def\expandafter\CatchFileDo
    \expandafter##\expandafter1\CatchFileEOF{\edef\CatchFileFinish{\endgroup
      \unexpanded{\edef#1{\unexpanded{##1}}}}}%
  #3\relax
  \expandafter\CatchFileDo\@@input #2\relax}
\begingroup
  \lccode65=64 % lowercase('A') = '@'
  \lccode66=64 % lowercase('B') = '@'
  \catcode65=8 % catcode('A') = subscript
  \catcode66=3 % catcode('B') = math shift
\lowercase{\endgroup
  \def\CatchFileEOF{AB}%
}
\makeatother

令牌\CatchFileEOF有两个@,第一个是 catcode 8,第二个是 catcode 3(任何人都不应该在文件中拥有它),本质上,执行的\easyCatchFiledef{\my}{file}{}

\def\CatchFileDo#1@@{%
  \edef\CatchFileFinish{\endgroup
    \unexpanded{\edef\my{\unexpanded{#1}}}}}%
\CatchFileDo<contents of file.tex>@@\CatchFileFinish

因为\expandafter之前的\CatchfileDo会扩展\@@input并显示 TeX 的内容file.tex。上面的行@@代表\CatchFileEOF特殊的分隔符标记。

实际上包含了当前版本 e-TeX 中不存在的catchfile.sty情况的代码,但这与讨论无关。Heiko 一如既往地做得很聪明。\unexpanded

答案2

据我所知,该宏可以通过一些 e-TeX 技巧来工作。如果没有这个技巧,如果您在可扩展上下文(如)中\CatchFileDef使用 TeX \input(在 LaTeX 中重命名为),则会收到错误。在这种情况下,会触发类似“检测到文件结尾时...”的错误。\@@input\edef

您的测试 4 不起作用,因为您在这里使用了\@@input简单的测试\def

\def\tempb{\@@input mylist.dat } 
\foreach \i in \tempb {..}

\tempb注意不是包含文件内容,而是\@@input包含文件名的宏,这对 来说并不好\foreach。这就像使用\foreach \i in {\@@input mylist.dat} {..},这没有多大意义。您需要\edef改为使用 来扩展 ,\@@input以便\tempb先包含文件内容。但是,如上所述,这不起作用。

\tempc测试 6 之所以有效,是因为您直接在输入文件中定义使用逗号分隔内容的宏,这在这里没有任何区别。测试 5 对您有用吗?这对我来说会更令人惊讶。

相关内容