# Extract all emphasized words from latex document

I need to produce a list of all words that are emphasised in my LaTeX document (=which are enclosed by \emph{...}).

How can I use awk to process the .tex file and extract all patterns starting with \emph{ and ending with a } and which do not contain a closing curly bracket within (otherwise almost the whole document would be matching the pattern). Finally, the result of the search should be a list like this:

1. FirstEmphasizedWord
2. AnotherEmphasizedWord
3. TheLastEmphasizedWord

(It would be nice if the list was already formatted as a numbered LaTeX list) What is the correct input for regular expression matching when I want to use awk for this job?

-
Hi Juri, Welcome to TeX.SE! Here's a link to a somewhat-related question http://tex.stackexchange.com/q/67709/6621 –  cmhughes Nov 1 '12 at 0:14
Welcome to TeX.sx! Usually, we don't put a greeting or a "thank you" in our posts. While this might seem strange at first, it is not a sign of lack of politeness, but rather part of our trying to keep everything very concise. Upvoting is the preferred way here to say "thank you" to users who helped you. –  Kurt Nov 1 '12 at 0:21

If you are not stuck on using an external script to do this, you can just do it LaTeX by redefining the \emph{} macro:

## Notes:

• Note how nested usage of \emph{} is treated (items 4 and 5 in the list). This may or may not be the desired behavior, but this should be fairly easy to change depending on the desired outcome.

## Code:

\documentclass{article}
\usepackage{letltxmacro}

% http://tex.stackexchange.com/questions/14393/how-keep-a-running-list-of-strings-and-then-process-them-one-at-a-time
\def\ListOfEmphText{}
\makeatletter
}
\makeatother

\LetLtxMacro\OldEmph\emph

\begin{document}
\emph{First emphasized Text,  with a comma} followed by
some normal text.
\emph{Second emphasized Text} followed by
some more normal text.

Some normal text before
\emph{Third emphasized Text} also followed by
some normal text

Here is some nested usage: \emph{abc \emph{def} ghi}, just to test that it works.

\bigskip\noindent
The macro \verb|\emph{}| was used on:
\begin{enumerate}
\ListOfEmphText
\end{enumerate}

\end{document}

-
I'm not sure, but I believe you don't want the new \emph to be robust, because then if you use it in \section argument and print \tableofcontents, it will appear twice in the list, won't it? (Of course, it depends on what is the desired behaviour) –  tohecz Nov 2 '12 at 10:07
@tohecz: Yes that does appear to be the case, but using \DeclareRobustCommand was suggested by egreg. An easy fix if that was not desired would be to move the redefinition of \emph to be after \tableofcontents. –  Peter Grill Nov 2 '12 at 17:33

Doing this with awk will be tricky as (AFAIK) it struggles with non-greedy regular expressions. Note that we'll need them to be non-greedy because of lines such as

\emph{multiple}  occurrences on the \emph{same line}


Perl can handle this pretty easily; you run the following script as

perl emphasize.pl myfile.tex


which will output to the terminal. Of course, you can output it into another file, such as

perl emphasize.pl myfile.tex> emphasizedtext.tex


Here's a test case:

myfile.tex

\documentclass{article}
\begin{document}

\emph{first} word is \emph{emphasized} and here's another \emph{one}.

here's another \emph{word} that is \emph{also} emphacized
\begin{enumerate}
\item \emph{should} also work
\item anywhere \emph{else too with multiple words}
\end{enumerate}
will struggle with nested: \emph{here is a \emph{nest}}
\end{document}


emhpasize.pl

#!/usr/bin/perl

use strict;
use warnings;

# for emphasized content
my @emphcontent=();
my $emphphrase=''; my$counter=0;

# loop through the lines in the INPUT file
while(<>)
{
# check for
#   \emph{}...
# and make sure not to match
#   %\emph{}...
# which is commented
if($_ =~ m/\\emph{(.*?)}/ and$_ !~ m/^%/)
{
# store the emphasized content
while($_ =~ m/\\emph{(.*?)}/g){ push(@emphcontent,$1);
}
}
}

# output the emphasized content
foreach $emphphrase (@emphcontent) {$counter++;
print $counter,". ",$emphphrase,"\n";
}

exit


output

1. first
2. emphasized
3. one
4. word
5. also
6. should
7. else too with multiple words
8. here is a \emph{nest


Or else you might prefer

# start the enumerate environment
print "\\begin{enumerate}\n";

# output the emphasized content
foreach $emphphrase (@emphcontent) { print "\\item ",$emphphrase,"\n";
}
# end the enumerate environment
print "\\end{enumerate}\n";


which gives

\begin{enumerate}
\item first
\item emphasized
\item one
\item word
\item also
\item should
\item else too with multiple words
\item here is a \emph{nest
\end{enumerate}


# Limitations

As you'll see, this script fails with nested {} and I have no idea how to fix it without some very convoluted code.

-
Your regex also fails in a case like \\emph{foo} (which hardly happens) that should not be matched... unless it's \\\emph{foo} unless.... It also fails with \emph {foo} (and maybe other cases I can't think of). Regexes are evil :( –  gniourf_gniourf Nov 5 '12 at 12:57
@gniourf_gniourf I could fix \emph {foo} pretty easily, but when would \\emph{foo} ever arise? –  cmhughes Nov 5 '12 at 16:22
For \\emph{foo}, I don't know! but it's valid (La)TeX code. Oh, also how about \emph{the set $\{42\}$ is non empty}? Regexes are evil :( –  gniourf_gniourf Nov 5 '12 at 17:41

Here's a LuaLaTeX solution using pattern matching. It can handle nesting easily (and by deleting a line can ignore nesting if desired). In addition, it can be turned on and off as desired. On the downside, since it uses the process_input_buffer callback, commented \emph's are included as well. I'm not sure how much of an issue this would be for you.

• \startgetemph turns on emph collection.
• \stopgetemph turns off emph collection.
• \printemphs returns a numbered list of emphs.

Output

\documentclass{article}
\usepackage{luacode,luatexbase}
\begin{luacode*}

emphs = {}
emphs[#emphs + 1] = hit
-- if you don't want nesting, then delete the following line
getemph(hit)
end
return true
end

printemphs = function()
tex.print("\\begin{enumerate}")
for i = 1, #emphs do
tex.print("\\item "..emphs[i])
end
tex.print("\\end{enumerate}")
end

\end{luacode*}

\def\stopgetemph{\directlua{luatexbase.remove_from_callback("process_input_buffer","getemph")}}
\def\printemphs{\directlua{printemphs()}}

\begin{document}

\startgetemph

\noindent
Here is some text where some of it is \emph{emphasized}.  Other parts will be \emph{emphasized \emph{twice}}.
%\emph{Oops, this is commented emphasized text!}
\stopgetemph
After using \verb=\stopgetemph=, \emph{this final emphasized text} will not be grabbed.

\printemphs
\end{document}

-
In Textwrangler (mac), do a search/replace for \\emph\{[a-z ]+\} Click "find all", you can then copy/paste the results into a new file. Do a new search/replace for all the newlines, inserting \\item. Very low-end.