
Dado um documento LaTeX, gostaria de usar um método automático para saber qual de todos os rótulos é o mais referenciado, qual é o segundo mais referenciado e assim por diante. Vou dar um exemplo para deixar claro. Suponha que temos este documento:
\documentclass{article}
\usepackage{amsthm}
\theoremstyle{plain}
\newtheorem{theorem}{Theorem}
\newtheorem{lemma}{Lemma}
\begin{document}
\begin{lemma}
\label{lm:1} Content of the first lemma.
\end{lemma}
Using lemma~\ref{lm:1} we have the following:
\begin{lemma}
\label{lm:2} Content of the second lemma.
\end{lemma}
Another consequence of lemma~\ref{lm:3} is the following:
\begin{lemma}
\label{lm:3} Content of the third lemma.
\end{lemma}
Finally, combining lemmas~\ref{lm:1},~\ref{lm:2},~\ref{lm:3} we have the following:
\begin{theorem}
\label{th:1}
\end{theorem}
\end{document}
Neste caso, a lista que gostaria de ver é a seguinte:
lm:1
lm:3
lm:2
º:1
Como lm:1 e lm:2 são referenciados duas vezes, outra lista aceitável é a seguinte:
lm:3
lm:1
lm:2
º:1
Não preciso de todas as listas possíveis, uma delas é suficiente.
Editar: e se, no processo de criação dessa lista, quisermos ignorar todos os rótulos que começam com um prefixo específico? Suponha que queiramos ignorar todos os rótulos que começam com “lm” no exemplo anterior. Então a saída desejada seria a seguinte:
- º:1
Responder1
Aqui está uma maneira:
\documentclass{article}
\usepackage{amsthm}
\usepackage{pgffor}
\theoremstyle{plain}
\newtheorem{theorem}{Theorem}
\newtheorem{lemma}{Lemma}
\let\oldref\ref
\let\oldlabel\label
\newcounter{labls}
\makeatletter
\def\ref#1{%
\@ifundefined{refrs@#1}{\xdef\temp{1}\expandafter\expandafter\expandafter\global\expandafter\let\csname refrs@#1\endcsname\temp}{%
\xdef\temp{\expandafter\expandafter\expandafter\number\expandafter\numexpr\csname refrs@#1\endcsname+1\relax}\expandafter\expandafter\expandafter\global\expandafter\let\csname refrs@#1\endcsname\temp\oldref{#1}}%
}
\def\label#1{%
\@ifundefined{labls@#1}
{\stepcounter{labls}}%
{Error:Already Defined Label: #1}
\@ifundefined{refrs@#1}{\xdef\temp{0}\expandafter\expandafter\expandafter\global\expandafter\let\csname refrs@#1\endcsname\temp}{\relax}%
\xdef\temp{#1}%
\expandafter\expandafter\expandafter\global\expandafter\let\csname LabelName\arabic{labls}\endcsname\temp\oldlabel{#1}%
}
\makeatother
\newcommand\reflist[1][]{%
\foreach\i in {1,...,\value{labls}}{%
\expandafter\expandafter\expandafter\global\expandafter\let\csname printed\i\endcsname\undefined%
}%
\foreach\k in {1,...,\value{labls}}{%
\xdef\maxRefs{-1}%
\xdef\printLabelNum{\k}%
\xdef\printLabelName{\csname LabelName\k\endcsname}%
\foreach \l in {1,...,\value{labls}}{%
\xdef\CurLabel{\csname LabelName\l\endcsname}%
\xdef\CurNum{\l}%
\xdef\CurRefs{\csname refrs@\CurLabel\endcsname}%
\ifnum\CurRefs > \maxRefs
\ifcsname printed\l\endcsname
\relax
\else
\xdef\maxRefs{\CurRefs}%
\xdef\printNum{\l}%
\fi
\fi
}%
{\bfseries \k)\csname LabelName\printNum\endcsname\xdef\t{#1}\ifx\t\empty\relax\else:~\maxRefs\fi\ifnum\k<\value{labls}\\\fi}%
\expandafter\expandafter\expandafter\global\expandafter\let\csname printed\printNum\endcsname\maxRefs%
}%
}
\begin{document}
\begin{lemma}
\label{lm:1} Content of the first lemma.
\end{lemma}
Using lemma~\ref{lm:1} we have the following:
\begin{lemma}
\label{lm:2} Content of the second lemma.
\end{lemma}
Another consequence of lemma~\ref{lm:3} is the following:
\begin{lemma}
\label{lm:3} Content of the third lemma.
\end{lemma}
Finally, combining lemmas~\ref{lm:1},~\ref{lm:2},~\ref{lm:3} we have the following:
\begin{theorem}
\label{th:1}
\end{theorem}
\noindent\reflist\vspace{1cm}
%You may add a non empty optional argument to print the appearances
\noindent\reflist[ ]
\end{document}
Responder2
Para esse tipo de aplicação, geralmente acho mais fácil usar uma linguagem de script que analise o arquivo de texto. Aqui está um exemplo com ferramentas Unix, onde seu arquivo é nomeadodoc.tex
sed "s:\}:\}\n:g" doc.tex |\
sed -rn "s:.*ref\{(.*)\}.*:\1:p" |\
sort | uniq --count
Isso produz
2 lm:1
1 lm:2
2 lm:3
Que você pode classificar canalizando-o parasort -r
O primeiro comando sed insere nova linha após }, o comando a seguir corresponde ao padrão \ref{}, mas apenas uma vez por linha, por isso o comando anterior é usado. Os comandos subsequentes são autoexplicativos.
Para ignorar os rótulos, você pode tornar o regex mais específico ou filtrar a saída acima