使用 `\readline` 时产生的错误

使用 `\readline` 时产生的错误

这个问题虽然与我之前问过这个问题,并不是关于从每行开头删除内容,而是关于如何在读取文件时预处理文件的行。

这是我想要预处理的文件:

  The character of the First Caesar has perhaps never been worse
  appreciated than by him who in one sense described it best; that is,

  \textbf{This is the first line.}\par
*  \textbf{This is the second line.}
*
*
*  Great as Caesar was by the benefit of his original nature, there can be
  no doubt that he, like others, owed something to circumstances; and

基本思想是,我在某处有一个布尔值集,它决定如何处理以 开头的行*。如果布尔值为假,这些行将被忽略:就像它们已被注释掉一样。如果布尔值为真,则处理这些行,就好像它们不是以星号开头一样。在这个 MWE 中,我没有任何布尔值。这个 MWE 应该表示如果布尔值设置为真,事情将如何处理。

梅威瑟:

\documentclass{article}

\makeatletter

\newread\file
\def\@gobblethree#1#2#3{}
\newcommand\myaccumulatedfile{}
\long\def\aegobbleinput#1{%
  \IfFileExists{#1}{%
    \openin\file #1
    \begingroup
    \endlinechar\newlinechar
    \loop\unless\ifeof\file
      \readline\file to\foo
%<a>%     \edef\myaccumulatedfile{\myaccumulatedfile\expandafter\@aegobble\foo\@nil}%%
%<b>%     \aftergroup\edef\myaccumulatedfile{\myaccumulatedfile\expandafter\@aegobble\foo\@nil}%%
    \repeat
    \closein\file
    \expandafter\endgroup
    \scantokens\expandafter{\myaccumulatedfile}
  }{%
    \errmessage{File `#1' doesn't exist!}%
  }%
}

\def\@aegobble{%%'
  \@ifnextchar*{\@@aegobble}{\@@nogobble}%%'
}

\def\@@aegobble*#1\@nil{Star}
\def\@@nogobble#1\@nil{#1Major}

\makeatother

\begin{document}

Try:

\aegobbleinput{test_file/star_test}

\end{document}

如上所述,这个 MWE 将会编译,但我已经注释掉了关键的几行。

如果以 开头的行%<a>%被取消注释,那么我会得到致命错误

! TeX capacity exceeded, sorry [input stack size=5000].
\foo ->
         The character of the First Caesar has perhaps never been worse
l.7 \aegobbleinput{test_file/star_test}
                                       ^^M
!  ==> Fatal error occurred, no output PDF file produced!

如果以 开头的行%<b>%被取消注释,那么我会得到非致命错误

Runaway definition?
\edef \edef \edef \edef \edef \edef \edef \edef 
! File ended while scanning definition of \edef.
<inserted text> 
                }
l.7 \aegobbleinput{test_file/star_test}

? 

最后一种方法似乎有些正确。至少生成的 PDF 接近我想要的格式。

我在这里做错了什么?

更新

根据 @jfbu 的建议,以下方法似乎有效:

\makeatletter
\newif\ifaeshowall
\aeshowallfalse
\long\gdef\aegobbleinput#1{%%'
  \begingroup
  \ifaeshowall\catcode`\*=9\relax\else\catcode`\*=14\relax\fi
  \input{#1}\endgroup}
\makeatother

答案1

正如评论中提到的那样,切换到使用"而不是*,或任何其他严格保留在输入文件中用作可能被省略的行的标签的字符,建议执行以下操作:

\def\doublequotecommentsout {\catcode`\"=14\relax}
\def\doublequoteisignored   {\catcode`\"=9\relax }
\def\makedoublequoteother   {\catcode`\"=12\relax }

然后包装该\input命令,或将其\InputIfFileExists放入所需的命令中。

在某些语言中,Babel 会使其"活跃,并且应该使用合适的 Babel 命令(\shorthandoff, \shorthandon)来代替上述命令,或者应该选择在该语言中不起作用的其他字符作为简写字符。

答案2

这个问题很难发现,因为在第一种情况下错误没有多大帮助,而在第二种情况下却没有透露太多信息!您有两个潜在问题。首先,\@ifnextchar是不可扩展的(不能在\edef或类似的函数内部使用)。在里面有一个赋值(\futurelet\@ifnextchar,而这在里面根本不会发生\edef。您可以定义一个可扩展的变体,\@ifnextchar但有一些限制(您必须抓取一个标记,因此如果例如“没什么可看的”,它可能会出错)。第二个问题是\aftergroup在组后插入一个标记,而不是很多标记。因此在文件的每一行的组后\aftergroup\edef\myaccumulatedfile插入一个\edef,然后直接放入\myaccumulatedfile输入“现在”。这种方法甚至不值得修复,因为\foo无论如何都会在组之后重置,所以您永远也得不到您想要的东西。

相关内容