![为什么这个宏定义宏后面的字符会被吞噬?](https://linux22.com/image/298409/%E4%B8%BA%E4%BB%80%E4%B9%88%E8%BF%99%E4%B8%AA%E5%AE%8F%E5%AE%9A%E4%B9%89%E5%AE%8F%E5%90%8E%E9%9D%A2%E7%9A%84%E5%AD%97%E7%AC%A6%E4%BC%9A%E8%A2%AB%E5%90%9E%E5%99%AC%EF%BC%9F.png)
我有以下纯 Tex 代码:
\def\xx{ABC}
\def\temp #1 {\def\tempii{#1}}
\temp\xx a b c
\tempii\tempii
我期望看到以下输出:
a b c ABCABC
但我确实看到了这个:
b c ABCaABCa
为什么 'a' 会被纳入 \tempii 的定义中?
答案1
我仍在思考为什么会这样,但这次修订(拥抱\xx
)给了你想要的东西。
我认为答案是,在使用中\temp\xx a b c
,后面的空格\xx
从 TeX 解析器的角度来看根本不是空格,而只是表示宏名称的结尾\xx
。例如,如果您只放\xx A
一行,您将看到它打印出来没有ABCA
空格。因此,解析器认为尾随的“A”与 相连\xx
。也可以使用\temp\xx{} a b c
,作为一种方式来告诉解析器空格是分隔符,而不仅仅是 后面的下一个字符\xx
。
\documentclass{article}
\begin{document}
\def\xx{ABC}
\def\temp #1 {\def\tempii{#1}}
\temp{\xx} a b c
\tempii\tempii
\end{document}
答案2
为了清楚起见,我将用 来表示空格标记•
,因为它们在讨论中非常重要;以下代码示例中的空格应该被忽略。
的参数文本\temp
是
#1•
而替换文本是
\def\tempii{#1}
您的电话\temp
是
\temp\xx a•b•c•\tempii\tempii
请注意,在\xx
宏的分隔符后面有一个空格;它是不是空格标记:没什么用,因为 TeX 总是忽略控制符后面的空格字(不控制符号)。后面的空格c
来自代码中的行尾。
扫描后面的标记\temp
(不进行扩展)以找到与参数文本匹配的标记,其中参数由空格分隔,因此#1
结束\xx a
,输入流的下一个状态是
\def\tempii{\xx a}b•c•\tempii\tempii
现在 TeX 执行定义并将其从输入流中删除:
b•c•\tempii\tempii
并将该部分b•c•
传递到排版阶段。在扩展了 的两个副本之后\tempii
,这相当于已经输入了
b•c•\xx a\xx a
或者
b•c•ABCaABCa
这正是你所得到的。
如果你使用\?
而不是\xx
最后两行将被转换成
\temp\?•a•b•c•\tempii\tempii
因为\?
是控制符号,而 TeX 不会忽略其后的空格。在这种情况下,结果将是
a•b•c•ABCABC
注意
\expandafter\temp\xx a•b•c
\tempii\tempii
会产生相同的结果,因为 TeX 的操作之后\expandafter
会呈现
\temp ABCa•b•c
\?
(当然,空格的约定与前面相同)。使用而不是\xx
使用,您将获得相同的结果
\expandafter\temp\expandafter\xx\space a•b•c
因为 TeX 将会呈现
\temp\xx•a•b•c
事实上,只有在标记化过程中,控制字后的空格才会被忽略。