命令/pageref{here}label{here}
可以打印出当前位置的所在页码,命令运行时可以直接在latex上渲染出来,现在我想把pageref{here}label{here}得到的页码写入到另外的txt文件中去,但是直接运行会报错,代码如下
\documentclass{article}
\usepackage{zref-abspage,lipsum}
\usepackage{fancyhdr}
\newwrite\myoutfile
\immediate\openout\myoutfile=\jobname-myoutfile.txt
\begin{document}
\lipsum[1-10]
\immediate\write\myoutfile{\pageref{here}\label{here}.}
\lipsum[10-12]
\end{document}
简单来说,当 label 不存在时,强行展开 \pageref
就会出现该错误。
第一次运行时,label 还没有写入 aux,这时,由于 \write
会自动展开它的参数,于是就出错了。
知道这之后,就容易解决了。
% \usepackage{expl3}% 在较新的 LaTeX2e 中是不必要的
\makeatletter
\ExplSyntaxOn
\cs_if_free:NT \use_ii:nnnnn
{ \cs_new:Npn \use_ii:nnnnn #1#2#3#4#5 { #2 } }
% 使用 hyperref,`\newlabel` 会写入 5 个参数,不使用 hyperref,则会写入 2 个参数,需要分别处理
% 第二个参数就是 page
\@ifpackageloaded{hyperref}
{
\cs_set_nopar:Npn \getrefpage #1
{ % 判断 label 是否存在,LaTeX 使用 "r@<label>" 保存 label
\cs_if_exist:cTF { r@#1 }
{ \exp_last_unbraced:Nv \use_ii:nnnnn { r@#1 } } % 获得5个中的第2个
{ 0 } % 若不存在则使用 0
}
}
{
\cs_set_nopar:Npn \getrefpage #1
{ % 同上
\cs_if_exist:cTF { r@#1 }
{ \exp_last_unbraced:Nv \use_ii:nn { r@#1 } }
{ 0 }
}
}
\ExplSyntaxOff
\makeatother
这样我们就可以使用 \getrefpage{<label>}
来获取 \label
定义的 label 的页码
\immediate\write\myoutfile{\getrefpage{nohere:a}}
\label{nohere:a} % label 需要在 \write 外部,才能创造一个label
由于 \label
是不可扩展的,若要在 \write
中写入,则需要使用 \noexpand
或 \string
:
\immediate\write\myoutfile{\getrefpage{nohere:a}\noexpand\label{nohere:a}}
\label{nohere:a}
另外,\label
中的 page 实际上是 \thepage
而不是绝对页码,也不一定是数字,例如修改了 page
计数器,或者使用了 \pagenumbering
。
此时,要想获得绝对页面,可以使用 zref-abspage
宏包,相应的,可以定义一个 \getzrefabspage
和 \getzrefpage
来获得绝对页码和相对页码。
% \usepackage{zref-abspage}
\makeatletter
\def\getzrefabspage#1{\zref@extract{#1}{abspage}}
\def\getzrefpage#1{\zref@ifrefundefined{#1}{0}{\zref@extract{#1}{page}}} % 同样需要检查是否存在
\makeatother
% \usepackage{zref-user,zref-abspage}
\zlabel{here:a}% 使用 \zlabel 而不是 \label
\immediate\write\myoutfile{\getzrefpage{here:a}\noexpand\zlabel{here:a}}
\immediate\write\myoutfile{\getzrefabspage{here:a}\noexpand\zlabel{here:a}}
当修改了 page
计数器,或者使用了 \pagenumbering
时,这二者是不同的。
一个完整的例子:
\documentclass{article}
% \usepackage{expl3}
\usepackage{zref-user,zref-abspage,lipsum}
\newwrite\myoutfile
\immediate\openout\myoutfile=\jobname-myoutfile.txt
\makeatletter
\def\getzrefabspage#1{\zref@extract{#1}{abspage}}
\def\getzrefpage#1{\zref@ifrefundefined{#1}{0}{\zref@extract{#1}{page}}}
\ExplSyntaxOn
\cs_if_free:NT \use_ii:nnnnn
{ \cs_new:Npn \use_ii:nnnnn #1#2#3#4#5 { #2 } }
\@ifpackageloaded{hyperref}
{
\cs_set_nopar:Npn \getrefpage #1
{
\cs_if_exist:cTF { r@#1 }
{ \exp_last_unbraced:Nv \use_ii:nnnnn { r@#1 } }
{ 0 }
}
}
{
\cs_set_nopar:Npn \getrefpage #1
{
\cs_if_exist:cTF { r@#1 }
{ \exp_last_unbraced:Nv \use_ii:nn { r@#1 } }
{ 0 }
}
}
\ExplSyntaxOff
\makeatother
\begin{document}
\immediate\write\myoutfile{\getzrefpage{here:a}\noexpand\zlabel{here:a}}
\immediate\write\myoutfile{\getzrefabspage{here:a}\noexpand\zlabel{here:a}}
\zlabel{here:a}
\immediate\write\myoutfile{\getrefpage{nohere:a}\noexpand\label{nohere:a}}
\label{nohere:a}
\lipsum[1-10]
\pagenumbering{alph}
\zlabel{here:b}.
\immediate\write\myoutfile{\getzrefpage{here:b}\noexpand\zlabel{here:b}}
\immediate\write\myoutfile{\getzrefabspage{here:b}\noexpand\zlabel{here:b}}
\label{nohere:b}.
\immediate\write\myoutfile{\getrefpage{nohere:b}\noexpand\label{nohere:b}}
\lipsum[10-12]
\end{document}
在较新的 LaTeX2e 发行版中,原生提供了 \ReadonlyShipoutCounter
和 totalpages
计数器来记录绝对页码。