Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I would like to obtain a plain text version of the index so thought it might be easier to extract it from the existing packages somehow. The MWE below produces:

enter image description here

What I want is a text file containing:

Fiction:
    Star Trek,

Jedi:
    Star Wars,

Science:
    Star Trek,

Science Fiction:
    Star Trek,
    Star Wars,

Spock:
    Star Trek,

Notes:

  • I have numerous files which will each be generating the temp files in a similar manner as below. I would like to post-process the all the temporary files and obtain a single combined index.
  • Not at all concerned with the page numbers.
  • I thought of writing a script that greps the files for the appropriate macros but thought that there might be a more elegant method either using the existing \index functionality or some other technique.
  • Not stuck on the syntax of the output. Anything that can easily be parsed is fine.
  • I don't know why I am getting a opening square bracket at the beginning of each entry, but apparently does not show up when others run similar code.

Code:

\documentclass{article}
\usepackage{lipsum}
\usepackage{imakeidx}

\makeindex[columns=2]

\newcommand*{\Index}[2]{%
    \newpage\lipsum[1]%  just for this MWE
    \index{#2!#1}%
}%

\begin{document}
  \Index{Star Trek}{Spock}
  \Index{Star Trek}{Science}
  \Index{Star Trek}{Science Fiction}

  \Index{Star Wars}{Jedi}
  \Index{Star Trek}{Fiction}
  \Index{Star Wars}{Science Fiction}

\printindex
\end{document}
share|improve this question
add comment

1 Answer

up vote 6 down vote accepted

1. Merging the unsorted index files

Your example generates an unsorted .idx file:

\indexentry{Spock!Star Trek}{1}
\indexentry{Science!Star Trek}{2}
\indexentry{Science Fiction!Star Trek}{3}
\indexentry{Jedi!Star Wars}{4}
\indexentry{Fiction!Star Trek}{5}
\indexentry{Science Fiction!Star Wars}{6}

As you want to ignore the page numbers, several .idx files can be merged by simple concatenation of the files, e.g. Linux/bash:

$ rm all.idx
$ cat *.idx >all.idx

Or in a command window in Windows:

> del all.idx
> type *.idx >all.idx

As result we have a file all.idx with all unsorted index entries.

2. Running makeindex

As makeindex always writes the page numbers, they have to be filtered out. The following style file `plain.ist for makeindex wraps the item names and page numbers in TeX commands to format or ignore them in a subsequent TeX run:

preamble "\\catcode`\{=1
\\catcode`\}=2
\\catcode`\#=6
\\expandafter\\ifx\\csname newwrite\\endcsname\\relax
  \\chardef\\OUT=10\\relax
\\else
  \\csname newwrite\\endcsname\\OUT
\\fi
\\immediate\\openout\\OUT=\\jobname.txt\\relax
\\def\\outaux#1{\\immediate\\write\\OUT{#1}}
\\def\\out#1{\\let\\out\\outaux}
\\def\\gobble#1{}
\\def\\space{ }
\\def\\spaces{\\space\\space\\space\\space}
"
postamble "\n\\immediate\\closeout\\OUT
\\csname @@end\\endcsname\\end\n"

setpage_prefix "\n\\gobble{"
setpage_suffix "}\n"

group_skip ""
headings_flag 0

item_0 "\n\\out{}\\out{"
item_1 "\n\\out{\\spaces "
item_2 "\n\\out{\\spaces\\spaces "
item_01 "\n\\out{\\spaces "
item_x1 ":}\n\\out{\\spaces "
item_x2 "}\n\\out{\\spaces\\spaces "
delim_0 ":}\\gobble{"
delim_1 "}\\gobble{"
delim_2 "}\\gobble{"
delim_t "}"
line_max 1000

Run makeindex with the specified style file:

makeindex -s plain.ist all.idx

The result is file all.ind:

\catcode`{=1
\catcode`}=2
\catcode`#=6
\expandafter\ifx\csname newwrite\endcsname\relax
  \chardef\OUT=10\relax
\else
  \csname newwrite\endcsname\OUT
\fi
\immediate\openout\OUT=\jobname.txt\relax
\def\outaux#1{\immediate\write\OUT{#1}}
\def\out#1{\let\out\outaux}
\def\gobble#1{}
\def\space{ }
\def\spaces{\space\space\space\space}

\out{}\out{Fiction:}
\out{\spaces Star Trek}\gobble{5}
\out{}\out{Jedi:}
\out{\spaces Star Wars}\gobble{4}
\out{}\out{Science:}
\out{\spaces Star Trek}\gobble{2}
\out{}\out{Science Fiction:}
\out{\spaces Star Trek}\gobble{3}
\out{\spaces Star Wars}\gobble{6}
\out{}\out{Spock:}
\out{\spaces Star Trek}\gobble{1}
\immediate\closeout\OUT
\csname @@end\endcsname\end

3.Running TeX

Some lines of the preamble and postamble of the generated file might look at little scary, they just ensure, that the file can be processed by different TeX formats (plain TeX, LaTeX) and even ini-TeX.

  • The code opens a file \\jobname.txt and writes lines into this file using macro \out.

  • The catcode settings are only needed by ini-TeX.

  • The trick of the redefinition of \out via \outaux helps to ignore the very first empty line of the very first item.

Now we can run TeX:

tex all.ind

4. Result

And the result is file all.txt:

Fiction:
    Star Trek

Jedi:
    Star Wars

Science:
    Star Trek

Science Fiction:
    Star Trek
    Star Wars

Spock:
    Star Trek
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.