当我在 \bool_until_do 循环内放置多个 \tl_use 命令时,LaTeX 无法完成编译(可能是无限循环)

当我在 \bool_until_do 循环内放置多个 \tl_use 命令时,LaTeX 无法完成编译(可能是无限循环)

我正在尝试使用 expl3 从 .aux 文件中检索数据。我想忽略第一行,因为它有不同的用途(因此是 \ior_str_get:NN \l_seccion_lista_ior \l_tmpa_tl)。以下行总是以三的倍数出现:节号、节名称和节开始的页面。我的问题是,如果我在循环中使用多个 \tl_use,循环似乎不会终止(它应该在文件读取完成时终止)。

下面是代码:

\file_if_exist:nTF {cap-\thechapter.aux}{
        \ior_new:N \l_seccion_lista_ior
        \ior_open:Nn \l_seccion_lista_ior {cap-\thechapter.aux}
        \ior_str_get:NN \l_seccion_lista_ior \l_tmpa_tl
        \bool_until_do:nn {\ior_if_eof_p:N \l_seccion_lista_ior}{
            \ior_get:NN \l_seccion_lista_ior \l_seccion_numero_tl
            \ior_get:NN \l_seccion_lista_ior \l_seccion_nombre_tl
            \ior_get:NN \l_seccion_lista_ior \l_seccion_pagina_tl
            \tl_trim_spaces:N \l_seccion_numero_tl 
            \tl_trim_spaces:N \l_seccion_nombre_tl 
            \tl_trim_spaces:N \l_seccion_pagina_tl
            \tl_use:N \l_seccion_numero_tl
            \tl_use:N \l_seccion_nombre_tl
            \tl_use:N \l_seccion_pagina_tl
            %[\l_seccion_numero_tl]~\l_seccion_nombre_tl~ (p.~\l_seccion_pagina_tl)\par
        }
        \ior_close:N \l_seccion_lista_ior
    }{}

.aux 文件的示例内容如下:

{\bool_gset_true:N \g_seccion_introduccion_bool}
{1.1}
{Tasas de cambio}
{2}
{1.2}
{Elasticidad puntual de la demanda}
{12}

非常感谢!

答案1

如果你变成\tl_use:N\tl_show:N得到

> \l_seccion_numero_tl={1.1}.
<recently read> }

l.41 \readauxfile{\jobname.txt}

?
> \l_seccion_nombre_tl={Tasas de cambio}.
<recently read> }

l.41 \readauxfile{\jobname.txt}

?
> \l_seccion_pagina_tl={2}.
<recently read> }

l.41 \readauxfile{\jobname.txt}

?
> \l_seccion_numero_tl={1.2}.
<recently read> }

l.41 \readauxfile{\jobname.txt}

?
> \l_seccion_nombre_tl={Elasticidad puntual de la demanda}.
<recently read> }

l.41 \readauxfile{\jobname.txt}

?
> \l_seccion_pagina_tl={12}.
<recently read> }

l.41 \readauxfile{\jobname.txt}

?
> \l_seccion_numero_tl=\par .
<recently read> }

看到发生了什么吗?文件末尾有一个隐含的空白行,你想检查它。

添加测试。

\begin{filecontents*}{\jobname.txt}
{\bool_gset_true:N \g_seccion_introduccion_bool}
{1.1}
{Tasas de cambio}
{2}
{1.2}
{Elasticidad puntual de la demanda}
{12}
\end{filecontents*}

\documentclass{article}

\ExplSyntaxOn

\ior_new:N \l_seccion_lista_ior
\tl_const:Nn \c_seccion_par_tl { \par }

\NewDocumentCommand{\readauxfile}{m}
 {
  \file_if_exist:nT {#1}
   {
    \ior_open:Nn \l_seccion_lista_ior {#1}
    % discard the first line
    \ior_str_get:NN \l_seccion_lista_ior \l_tmpa_tl
    % read the rest
    \bool_until_do:nn {\ior_if_eof_p:N \l_seccion_lista_ior}
     {
      \ior_get:NN \l_seccion_lista_ior \l_seccion_numero_tl
      % check if empty line
      \tl_if_eq:NNF  \l_seccion_numero_tl \c_seccion_par_tl
       {
        \ior_get:NN \l_seccion_lista_ior \l_seccion_nombre_tl
        \ior_get:NN \l_seccion_lista_ior \l_seccion_pagina_tl
        \tl_trim_spaces:N \l_seccion_numero_tl 
        \tl_trim_spaces:N \l_seccion_nombre_tl 
        \tl_trim_spaces:N \l_seccion_pagina_tl
        [\l_seccion_numero_tl]~\l_seccion_nombre_tl\c_space_tl (p.~\l_seccion_pagina_tl)\par
       }
     }
    \ior_close:N \l_seccion_lista_ior
   }
 }

\ExplSyntaxOff

\begin{document}

\readauxfile{\jobname.txt}

\end{document}

适应您的设置。请注意,忽略~之后,我使用了。\l_seccion_nombre_tl\c_space_tl

在此处输入图片描述

避免最后隐式空行问题的不同策略:

\begin{filecontents*}{\jobname.txt}
{\bool_gset_true:N \g_seccion_introduccion_bool}
{1.1}
{Tasas de cambio}
{2}
{1.2}
{Elasticidad puntual de la demanda}
{12}
\end{filecontents*}

\documentclass{article}

\ExplSyntaxOn

\ior_new:N \l_seccion_lista_ior
\seq_new:N \l_seccion_items_seq

\NewDocumentCommand{\readauxfile}{m}
 {
  \file_if_exist:nT {#1}
   {
    \ior_open:Nn \l_seccion_lista_ior {#1}
    \seq_clear:N \l_seccion_items_seq
    % discard the first line
    \ior_str_get:NN \l_seccion_lista_ior \l_tmpa_tl
    % read the rest
    \ior_map_inline:Nn \l_seccion_lista_ior
     {
      \seq_put_right:Nn \l_seccion_items_seq { ##1 }
     }
    \ior_close:N \l_seccion_lista_ior
    \seq_map_indexed_inline:Nn \l_seccion_items_seq
     {
      \int_case:nn { \int_mod:nn { ##1 } { 3 } }
       {
        {1}{ [\tl_trim_spaces:n { ##2 }] ~ }
        {2}{ \tl_trim_spaces:n { ##2 } ~ }
        {0}{ (p.\nobreakspace\tl_trim_spaces:n { ##2 })\par }
       }
     }
   }
 }

\ExplSyntaxOff

\begin{document}

\readauxfile{\jobname.txt}

\end{document}

对于没有达到所需行数(3 的倍数加 1)的不正确文件,此解决方案也更加强大。

答案2

TeXbook 在第 20 章:定义(也称为宏)中说道:

要从打开的文件中获取输入,您可以说,
\read⟨number⟩to⟨control sequence⟩
并且控制序列被定义为无参数宏,其替换文本是从指定文件读取的下一行的内容。根据当前类别代码,使用第 8 章的过程将此行转换为标记列表。
如果需要,将读取其他行,直到找到相等数量的左括号和右括号。一个空行被隐式地添加到正在被复制的文件的末尾。\read

注意句子一个空行被隐式地添加到正在被复制的文件的末尾。\read

隐式附加的空行会产生循环的额外迭代,其中

  • \l_seccion_numero_tl由于隐式附加的行为空,因此为空。
  • \l_seccion_nombre_tl容纳夸克\q_no_value
  • \l_seccion_pagina_tl 容纳夸克\q_no_value

在此迭代中,指令\tl_use:N \l_seccion_nombre_tl产生夸克\q_no_value
夸克的一个特性是,扩展形成夸克的标记会产生夸克。
扩展\q_no_value会产生\q_no_value
因此,扩展的尝试\q_no_value会导致 TeX 陷入无限循环。

也许您只能\tl_use:N在执行下列操作时未到达文件末尾的情况下执行 -thingies操作\ior_get:NN :

文件:cap-1.aux- 在您的场景中,文件似乎在\ExplSyntaxOn有效时被读取,因此用于~获取正常的空间标记:

{\bool_gset_true:N \g_seccion_introduccion_bool}
{1.1}
{Tasas~de~cambio}
{2}
{1.2}
{Elasticidad~puntual~de~la~demanda}
{12}

最小可验证可重现完整示例:

\documentclass{report}

\begin{document}
\chapter{whatsoever}
\ExplSyntaxOn
\file_if_exist:nTF {cap-\thechapter.aux}{
        % Don't do \ior_new:N within a macro's replacement text 
        % unless you want another `\read`-handle allocated whenever
        % carrying out an instance of that macro!
        \ior_new:N \l_seccion_lista_ior
        \ior_open:Nn \l_seccion_lista_ior {cap-\thechapter.aux}
        \ior_str_get:NN \l_seccion_lista_ior \l_tmpa_tl
        \bool_until_do:nn {\ior_if_eof_p:N \l_seccion_lista_ior}{
            \ior_get:NN \l_seccion_lista_ior \l_seccion_numero_tl
            \ior_get:NN \l_seccion_lista_ior \l_seccion_nombre_tl
            \ior_get:NN \l_seccion_lista_ior \l_seccion_pagina_tl
            \tl_trim_spaces:N \l_seccion_numero_tl 
            \tl_trim_spaces:N \l_seccion_nombre_tl 
            \tl_trim_spaces:N \l_seccion_pagina_tl
%             \tl_show:N \l_seccion_numero_tl
%             \tl_show:N \l_seccion_nombre_tl
%             \tl_show:N \l_seccion_pagina_tl
            \ior_if_eof:NF \l_seccion_lista_ior {
              \tl_use:N \l_seccion_numero_tl \\
              \tl_use:N \l_seccion_nombre_tl \\
              \tl_use:N \l_seccion_pagina_tl \\
              %[\l_seccion_numero_tl]~\l_seccion_nombre_tl~ (p.~\l_seccion_pagina_tl)\par
            }
        }
        \ior_close:N \l_seccion_lista_ior
    }{}
\ExplSyntaxOff
\end{document}

相关内容