类似 `\ignorespaces` 的宏用于忽略 `\par`

类似 `\ignorespaces` 的宏用于忽略 `\par`

我想要一个宏来\ignorepars删除\par其后的所有 s。我写了以下代码:

\def\eat{}
\def\ignorepars{\futurelet\next\ignoreparsA} 
\def\ignoreparsA{\ifx\next\par\expandafter\ignorepars\eat\fi}

但它不起作用(它会导致 TeX 容量超出错误)。例如,假设我有\ignorepars\par x。然后,根据我的说法,扩展\ignorepars使得\next类似于\par并且标记列表变为\ignoreparsA\par x;接下来扩展后\ignoreparsA它保持为\expandafter\ignorepars\eat\par x;因此,在另一次扩展之后,标记列表变为\ignorepars x;这使得\next具有值 x 并扩展为\ignoreparsA x;由于谓词为假,因此这会扩展为空\ifx

但实际上发生了什么?

编辑: \def\eat{}应该是\long\def\eat#1{} (这是一个打字错误)

答案1

我们慢慢来吧:

\ignorepars\par x

变成

\futurelet\next\ignoreparsA\par x

现在\next\let\par并且\ignoreparsA是扩展的,所以我们有

\ifx\next\par\expandafter\ignorepars\eat\fi\par x

条件为真,所以\ifx\next\par消失,留下

\expandafter\ignorepars\eat\fi\par x

现在\expandafter展开\eat,其展开式为空,所以我们有

\ignorepars\fi\par x

OK,\ignorepars展开如下:

\futurelet\next\ignoreparsA\fi\par x

现在\next\let并且\fi正在\ignoreparsA扩大

\ifx\next\par\expandafter\ignorepars\eat\fi\fi\par x

条件为假,所以我们得到

\fi\par x

最后,的扩展\fi为空。因此,如您所见,没有\par被吞掉。事实上,测试文件

\def\eat{}
\def\ignorepars{\futurelet\next\ignoreparsA}
\def\ignoreparsA{\ifx\next\par\expandafter\ignorepars\eat\fi}

x\ignorepars\par x

\bye

不会导致 TeX 容量超出,但会打印两个段落。

如果你的定义\eat

\def\eat#1{}

那么你确实会陷入无限循环,因为\eat会一次又一次地吞噬\fi并呈现 TeX 。\ignorepars\par


你有更好的运气

\long\def\eat#1{\ignorepars}
\def\ignorepars{\futurelet\next\ignoreparsA}
\def\ignoreparsA{\ifx\next\par\expandafter\eat\fi}

x\ignorepars\par x

\bye

摆脱\expandafter\fi\eat吞噬\par令牌和供应\ignorepars

测试文件

\long\def\eat#1{\ignorepars}
\def\ignorepars{\futurelet\next\ignoreparsA}
\def\ignoreparsA{\ifx\next\par\expandafter\eat\fi}

x\ignorepars\par x

y\ignorepars

y

z\ignorepars



z

\bye

在此处输入图片描述

答案2

这比 egreg 的建议少了很多技巧,但有时蛮力是有效的。

\let\oldpar\par
\def\ignorepar{\let\par\ignorespaces}
\def\restorepar{\endgraf\let\par\oldpar}
\def\bye{\endgraf\end}

\ignorepar

abcdef ghijkl mnopqr stuv wxyz

abcdef ghijkl mnopqr stuv wxyz

abcdef ghijkl mnopqr stuv wxyz

abcdef ghijkl mnopqr stuv wxyz

\restorepar

abcdef ghijkl mnopqr stuv wxyz

abcdef ghijkl mnopqr stuv wxyz

\ignorepar

abcdef ghijkl mnopqr stuv wxyz

abcdef ghijkl mnopqr stuv wxyz

abcdef ghijkl mnopqr stuv wxyz

abcdef ghijkl mnopqr stuv wxyz

\restorepar

abcdef ghijkl mnopqr stuv wxyz

abcdef ghijkl mnopqr stuv wxyz

\bye

答案3

空格需要特殊处理才能被忽略,因为它们是字符标记,但是\par是一个 csname,所以您可以更简单地执行 \let\par\empty (例如,latex 在中执行的操作tabular)(如果以这种方式被忽略,显然您需要一些钩子(例如组末尾)来恢复定义\par。)

相关内容