含\relax的\newcommand生成额外空格问题及解决咨询
发现用\relax定义的\newcommand会生成额外空格。测试了两个自定义命令:一个基于\relax,另一个基于\marginpar。直接使用\relax的语句与无命令语句结果一致,但使用自定义\relax命令时会出现意外空格,需手动删除命令与文本间的空格才能匹配预期;而基于\marginpar的自定义命令表现正常。尝试过\ignorespaces但无效,想了解这是LaTeX特性还是命令定义问题,以及如何修改命令使其与\marginpar表现一致。
测试代码
\documentclass{article} \newcommand{\testcmdMarginPar}[1]{\marginpar{#1}} \newcommand{\testcmd}[1]{\relax} \begin{document} sdfsdfds this is a test sdfsdfds \relax this is a test sdfsdfds \testcmd{abc} this is a test sdfsdfds \testcmd{abc}this is a test sdfsdfds\testcmd{abc} this is a test ----------------------------------- sdfsdfds\testcmdMarginPar{abc} this is a test sdfsdfds \testcmdMarginPar{abc} this is a test sdfsdfds \testcmdMarginPar{abc} this is a test sdfsdfds this is a test \end{document}
测试结果
sdfsdfds this is a test
sdfsdfds this is a test
sdfsdfds this is a test
sdfsdfds this is a test
sdfsdfds this is a test
———————————–
sdfsdfds this is a test abc
sdfsdfds this is a test abc
sdfsdfds this is a test abc
sdfsdfds this is a test
原因分析
这是LaTeX命令处理机制的特性:
- 直接使用
\relax时,它作为LaTeX内置的“空操作”控制序列,后面的空格会被LaTeX视为命令结束的标记,自动忽略。 - 自定义的
\testcmd展开后仅为\relax,但LaTeX处理完自定义命令的调用(包括参数解析)后,后续的空格不会被自动忽略——因为自定义命令本身没有内置忽略后续空格的逻辑。 \marginpar是LaTeX内核命令,其实现中包含了处理参数后自动跳过后续空格的逻辑,因此命令后的空格会被忽略。
解决方法
要让自定义的\testcmd和\marginpar表现一致,需要在命令定义中加入\ignorespacesafterend,让命令执行后自动忽略后续的空格。由于\ignorespacesafterend是带@的内部命令,需要用\makeatletter和\makeatother包裹定义:
\documentclass{article} \newcommand{\testcmdMarginPar}[1]{\marginpar{#1}} \makeatletter \newcommand{\testcmd}[1]{\relax\ignorespacesafterend} \makeatother \begin{document} % 原测试内容不变 \end{document}
修改后,\testcmd{abc}后面的空格会被自动忽略,输出效果与直接使用\relax或\testcmdMarginPar一致。
内容的提问来源于stack exchange,提问作者im-Kitsch

