我正在尝试使用 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}