# Using sed to match multiple possible environments in a file

I have some files numbered 01 to 24 that contain things like

\begin{thm}
blah blah blah
\end{thm}
\begin{lem}
blah blah blah
\end{lem}
\begin{prop}
blah blah blah
\end{prop}


inside of them and I want to extract every one of these matches from the file (together with the 'blah blah blah' of course). So I was happily using

sed -n '/\\begin{FOO}/,/\\end{FOO}/p' ./*.tex >> newfile.txt


and running the above with FOO replaced by thm then lem then prop. But I realised I am stupid because the order is all mixed up now in newfile.txt in the sense that all the \begin{thm}...\end{thm} precede all the begin{lem}...\end{lem} precede all the begin{prop}...\end{prop} even if they follow one another in one of the files say, but I want to keep them in the order that they appear in the files.

Question: How can I get sed to extract all of these case at once, and thus preserve the order that they appear in the files?

-
Is \end{FOO} always on the same line as \begin{FOO}? That's unusual. – Gilles Dec 29 '13 at 20:14
It is not always on the same line, I guess I should have made that clear. – sdf Dec 31 '13 at 7:19

If I got you right, you need to get all ranges at once. You can do it with following sed construction:

sed -n '/\\begin{FOO}/,/\\end{FOO}/p;
/\\begin{FOO1}/,/\\end{FOO1}/p;
/\\begin{FOO2}/,/\\end{FOO2}/p;' ./*.tex >> newfile.txt


where FOO == thm, FOO1 == lem, FOO2 == prop.

-

You seem to have needlessly complicated things, if these are all single lines, all you need is

sed -n '/\\begin{FOO}/p' >> newfile.txt


Not sure why you are also matching the \end unless you want to exclude any text that comes afterwards (but your sed command won't).

Anyway, an easier way would be to just use grep instead:

grep -P '\\begin\{(thm|prop|lem)\}' *tex


Or, in sed:

sed -n '/\\begin{thm}/p; /\\begin{prop}/p; /\\begin{lem}/p' *tex


Or Perl:

perl -ne 'print if /\\begin{thm|lem|prop}/' *tex

-
I think what the question omits is that the \end{FOO} may be (and usually is) on a different line from \begin{FOO}. – Gilles Dec 29 '13 at 20:13
As above, this won't work for me because they don't appear on the same line, I guess I should have made this more clear in the statement. – sdf Dec 31 '13 at 7:20