
LaTeX 문서가 주어지면 자동 방법을 사용하여 모든 레이블 중 어느 레이블이 가장 많이 참조되는지, 어느 레이블이 두 번째로 가장 많이 참조되는지 등을 알고 싶습니다. 명확하게 설명하기 위해 예를 들어 보겠습니다. 다음 문서가 있다고 가정해 보겠습니다.
\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}
이 경우 보고 싶은 목록은 다음과 같습니다.
작품:1
작품:3
작품:2
일:1
lm:1과 lm:2는 모두 두 번 참조되므로 허용되는 또 다른 목록은 다음과 같습니다.
작품:3
작품:1
작품:2
일:1
가능한 모든 목록이 필요하지는 않습니다. 그 중 하나만 있으면 충분합니다.
편집: 그러한 목록을 만드는 과정에서 특정 접두어로 시작하는 모든 레이블을 무시하려면 어떻게 해야 합니까? 이전 예에서 "lm"으로 시작하는 모든 레이블을 무시한다고 가정해 보겠습니다. 그러면 원하는 출력은 다음과 같습니다.
- 일:1
답변1
방법은 다음과 같습니다.
\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}
답변2
이런 종류의 응용 프로그램에서는 텍스트 파일을 구문 분석하는 스크립팅 언어를 사용하는 것이 더 쉽다는 것을 종종 알게 됩니다. 다음은 파일 이름이 지정된 Unix 도구의 예입니다.doc.tex
sed "s:\}:\}\n:g" doc.tex |\
sed -rn "s:.*ref\{(.*)\}.*:\1:p" |\
sort | uniq --count
이 출력
2 lm:1
1 lm:2
2 lm:3
그런 다음 파이핑하여 정렬할 수 있습니다.sort -r
첫 번째 sed 명령은 } 뒤에 개행 문자를 삽입하고, 다음 명령은 \ref{} 패턴과 일치하지만 한 줄에 한 번만 일치하므로 이전 명령이 사용되는 이유입니다. 후속 명령은 설명이 필요하지 않습니다.
라벨을 무시하려면 정규식을 더 구체적으로 만들거나 위의 출력을 필터링하면 됩니다.