• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

[gelöst] LaTeX: Liste aller Querverweise

xxxsemoi

Member
Servus,
weiss jemand, wie man eine Liste aller Querverweise MIT Seitenangabe erhält. Wenn also auf Seite 10 eine Abbildung mit \label{fig:blablubb} steht und auf Seite 65 und Seite 89 ein Verweis \ref{fig:blablubb} oder \pageref{fig:blablubb}, dann soll eine Datei erstellt werden, die wie folgt aussieht
Code:
\label{fig:blablubb} auf Seite 10
     Querverweise dazu auf Seite 65, 89

\label{fig:....} auf Seite ...
     Querverweise dazu auf Seite ...
.
.
.
Die genaue Form ist dabei natürlich egal. Mir ist jedes Format recht, falls die Datei nur die Seiten der labels und die Seiten der Referenzen beinhaltet. Also auch etwas wie
Code:
\label{fig:blablubb}, Seite 10
\label{....}, Seite ...
.
.
.


\ref{fig:blablubb}, Seite 65
\ref{...}, Seite ...
.
.
.
\ref{fig:blablubb}, Seite 89
.
.
.
Weiss da jemand Rat?
Gruß
xxxsemoi



LÖSUNG von anglo
Das folgende in die Preample der LaTeX-Datei kopieren
Code:
%% Liste allen Referenzen und Seitenangaben in Datei mit Endung ".ref"
\makeatletter
\newcommand{\reffile}{\jobname.ref}
\newcommand{\openfile}[1]{\newwrite\outfile\openout\outfile=#1}
\newcommand{\closefile}[1]{\closeout\outfile}
\immediate\openfile{\reffile}\relax
\AtEndDocument{\closefile\reffile}
\makeatother
%% nun definieren wir die Befehle  \label, \ref, \refpage um
\let\ltxlabel=\label
\let\ltxref=\ref
\let\ltxpageref=\pageref
\renewcommand{\label}[1]{%
  \write\outfile{label #1 on page \thepage}%
  \ltxlabel{#1}%
}
\renewcommand{\ref}[1]{%
  \write\outfile{ref #1 on page \thepage}%
  \ltxref{#1}%
}
\renewcommand{\pageref}[1]{%
  \write\outfile{pageref #1 on page \thepage}%
  \ltxpageref{#1}%
}
 
Eine Untermenge der gesuchten Funktionalität stellt das Paket hyperref mit der Option backref zur Verfügung.

Greetz, HB
 
OP
xxxsemoi

xxxsemoi

Member
Danke für deine schnelle Antwort.
Leider scheint mir das nicht die Lösung meines Problems zu sein. Ich bin nicht daran interessiert, im Literaturverzeichnis Rückverknüpfungen zu plazieren, sondern meine Bilder richtig anzuordnen. Ich möchte eine schnellen Test machen können, ob die Bilder auf der gleichen Doppelseite erscheinen, auf der sie auch das erste Mal referenziert werden. Falls man ein Bild erklärt ist es nämlich viel einfacher für den Leser, falls er es auch vor Augen hat.
Trotzdem Danke
Gruß xxxsemoi
 
Die Einschränkung, das Bild dort zu platzieren, würde ich mir aber nicht antun. Stattdessen kannst du besser mit \pageref{fig:blabla} auf die Seitenzahl des Bildes verweisen.

Greetz, HB
 

anlo

Newbie
die Infos, auf welcher Seite die Labels liegen steckt in der aux-Datei

Code:
\newlabel{BEZEICHNER}{{ABSCHNITTNUMMER}{SEITE}}

d.h. die kannst Du Dir einfach mit einem Script da rauslesen. Für ein Projekt mit 100erten von Labeln :) hab ich mir da mal ein kleines Perlscript gebaut (das ist mehr grauenvoll als alles andere ;) )

Code:
#!/usr/bin/perl -w

use strict;


# write Header
print "\\documentclass[a4paper]{article}\n";
print "\\title{Labelliste}\n";
print "\\begin{document}\n";
print "\\maketitle\n";
print "\\section{Anfang des Dokuments}\n";
print "\\begin{tabular}{l|l|l}\n";
print "Labelname & Labelnummer & auf Seite\\\\\\hline\n";



while (<>)
{
  # new section found
  if ( /toc/ && /contentsline/ )
  {
    m/^[^\{]*\{toc\}\{(.*)\}$/;
    $1 =~ m/^[^\{]*(.*)/;
    $1 =~m/^\{([^\}]*)\}\{(.*)\}\{([^\}]*)\}$/;
    my $secname = $1;
    my $page = $3;
    $2 =~ m/\{([^\}]*)\}(.*)$/;
    my $secnumb = $1;
    my $sectitle = $2;
    print "\\end{tabular}\n";
    print "\\section{In $secname $secnumb\\\\($sectitle auf Seite $page)}\n";
    print "\\begin{tabular}{l|l|l}\n";
    print "Labelname & Labelnummer & auf Seite\\\\\\hline\n";
  }

  # \newlabel{foo}{{nmblne}{page}}
  # ignore the vref @-labelnames
  if (/newlabel\{([^\}|@]*)\}\{\{([^\}]*)\}\{([^\}]*)\}\}/)
  {
    print "$1& $2 & $3 \\\\\\hline\n";
  }
}

# write footer
print "\\end{tabular}\n";

print "\\end{document}\n";
das schreibt eine neue Tex-Datei mit entsprechenden Infos, auf welcher Seite welches Label steht, Aufruf:

Code:
./scriptname < foo.aux > labelliste.tex
damit weiß man natürlich nicht, wo die \refs liegen -> die Infos stecken leider aber nicht in den .aux oder .log-Files drin :( war damals aber nicht weiter wichtig, so dass ich das nicht weiter verfolgt habe :) müsste ich bei Zeitne mal etwas aufhübschen...

Du solltest Dir evtl. auch mal das Paket varioref ansehen, dann kannst Du mit \vref{foo} arbeiten und bekommst u.a. "dieser Seite", "der vorigen/nöchsten Seite" oder " Seite XYZ" das ist schon mal deutlich schöner zu lesen.
 
OP
xxxsemoi

xxxsemoi

Member
Ich kenne varioref, habe es aber noch nie benutzt. Muss ich vielleicht einmal nachholen.
Ich verstehe nichts (!) von Perl, aber ein Abbildungs- bzw. Tabellenverzeichnis kann ich leichter durch
Code:
\listoffigures
\listoftables
erhalten. Mir geht es wirklich um die Seiten auf denen die Referenzen erscheinen.
Trotzdem danke für die Antwort.
Gruß xxx
 

joka

Member
xxxsemoi schrieb:
Weiss da jemand Rat?
Ja! Wie anlo geschrieben hat steckt die Info, auf welcher Seite die Labels liegen, in der aux-Datei -- aber nur für die \label-Definitionen.

Man muss also das \ref und \pageref Makro so ergänzen, dass es diese Info auch schreibt, z.B. mit einem eigenem \label-Aufruf. Das geht z.B. so (hinter \begin{document} einfügen*):
Code:
\let\ltxpageref=\pageref
\let\ltxref=\ref
\renewcommand{\pageref}[1]{\label{Ref:#1}\ltxpageref{#1}}
\renewcommand{\ref}[1]{\label{Ref:#1}\ltxref{#1}}
Mit diesen erweiterten \ref-Definitionen wird an jeder \ref und \pageref Stelle ein Eintrag \newlabel{Ref:BEZEICHNER}{{ABSCHNITTNUMMER}{SEITE}} geschrieben, den man dann mit grep- sed- und/oder sonstigen Skripten aus der aux-Datei auslesen kann.

Beispiel:
Code:
$ grep '\newlabel' texdatei.aux
...
\newlabel{Ref:sec:sample}{{2.3}{12}{Bla bla\relax }{figure.2.2}{}}
\newlabel{sec:sample}{{2.4.2}{16}{Bla bla }{subsection.2.4.2}{}}
...

*) Achtung: das hyperref-Paket überschreibt ebenfalls die \ref und \pageref-Makros bei der Abarbeitung von \begin{document}. Deswegen müssen die Makros dahinter eingefügt werden.
 

anlo

Newbie
die Idee mit den Refs ist nicht schlecht führt aber IMHO zu unschönen Warnings :) wenn Du einen label mehrfach referenzierst, dann bekommst Du entsprechende multi-defined-labels, hier fallen mir 2 Lösungen ein:

a/ einen eigenen Zähler hinzunehmen und dann die "extra" label entsprechend nummerieren

b/ die ganzen Infos in eine extra-Datei schreiben :) und da hab ich mir gerade mal ein paar Gedanken zu gemacht. insbesondere hat das den Vorteil, dass man das gleiche Format generieren kann egal ob man hyperref nutzt oder nicht.

in die Präambel
Code:
\makeatletter
\newcommand{\reffile}{\jobname.ref}
\newcommand{\openfile}[1]{\newwrite\outfile\openout\outfile=#1}
\newcommand{\closefile}[1]{\closeout\outfile}

\immediate\openfile{\reffile}\relax
\AtEndDocument{\closefile\outfile}
\makeatother

die Umdefinierung wie von joka geschrieben hat so bei hyperref Probleme :( hier müsste man sich u.u. noch einen anderen Hook suchen aber egal, jetzt einfach wieder ins Dokument:

Code:
\let\ltxpageref=\pageref
\let\ltxref=\ref
\let\ltxlabel=\label
\renewcommand{\pageref}[1]{%
  \write\outfile{pageref #1 on page \thepage}%
  \ltxpageref{#1}%
}
\renewcommand{\ref}[1]{%
  \write\outfile{ref #1 on page \thepage}%
  \ltxpageref{#1}%
}
\renewcommand{\label}[1]{%
  \write\outfile{label #1 on page \thepage}%
  \ltxlabel{#1}%
}

bei einem Durchlauf wird jetzt eine neue Datei <LATEX-DATEI>.ref erzeugt, die sieht so aus:

Code:
$ cat foo.ref
label chp:foo on page 3
ref chp:baz on page 3
label chp:bar on page 5
ref chp:foo on page 5
label chp:baz on page 7
ref chp:bar on page 7
pageref chp:foo on page 7
 
OP
xxxsemoi

xxxsemoi

Member
Danke Euch,
der Vorschlag von anglo funktioniert prima. Habe nur den vorletzten Eintrag
Code:
\AtEndDocument{\closefile\outfile}
umgeändert zu
Code:
\AtEndDocument{\closefile\reffile}
.
Danke.
xxxsemoi
 

anlo

Newbie
xxxsemoi schrieb:
Danke Euch,
der Vorschlag von anglo funktioniert prima. Habe nur den vorletzten Eintrag
Code:
\AtEndDocument{\closefile\outfile}
umgeändert zu
Code:
\AtEndDocument{\closefile\reffile}
.

und warum? hast Du überhaupt eine Ahnung was da passiert?

Oh, Mann... wenn Du wüsstest was die Zeilen machen, wäre dir klar, dass das völliger Schwachsinn ist.
 
OP
xxxsemoi

xxxsemoi

Member
Ich habe keine Ahnung was da passiert, da ich von TeX überhaupt nichts verstehe. Ich hantiere nur mit LaTeX rum. Ich hatte einfach vermutet: Falls das Ende des Documentes erreicht ist, dann schließe die Datei.
Mit Deinem Code konnte ich die Dateien nicht mehr kompilieren. Ich dachte, dass das damit zusammenhängt, dass ich mehr als 16 Dateien gleichzeitig öffne. Mit der kleinen Änderung sah die .ref-Datei richtig aus.
Was macht den der Befehl?
 

anlo

Newbie
xxxsemoi schrieb:
Ich habe keine Ahnung was da passiert, da ich von TeX überhaupt nichts verstehe.
Ach...


OK, erstmal: Sorry, im Prinzip hast Du fast recht :) *aber* auch nur fast. LaTeX frisst die Syntax zwar, aber richtiger wäre (siehe deklaration von closefile)
Code:
\AtEndDocument{\closefile{\reffile}}
*aber* das ist hier völlig egal :) noch Sinnvoller
ist :
Code:
\newcommand{\closefile}{\closeout\reffile}
\AtEndDocument{\closefile}

Du könntest natürlich auch stattdessen schreiben:
Code:
\AtEndDocument{\closeout\outfile}
(Beachte Unterschied closeout und closefile :)

Zudem würde ich das Immediate noch rausnehmen, also ein
Code:
\openfile{\reffile}
Falls das Ende des Documentes erreicht ist, dann schließe die Datei.
genau und die Datei wird über ein Handle gleschlossen -> und das Handle ist \outfile

Mein Fehler kommt von Schlampigem C&P ;)
 
Oben