# How to extract lines starting with a pattern and chunks between two patterns?

I have files (say, infile.tex) of the form

AAAA
BBBB AAAA
CCCC BBBB AAAA

%%## Just some text
\begin{example}[foobar]
\begin{Sinput}
> set.seed(271)
> U <- runif(10)
> plot(U, 1-U)
\end{Sinput}
AAAA BBBB CCCC
\begin{Sinput}
> plot(qnorm(cbind(U, 1-U)))
\end{Sinput}
\end{example}


and I would like to extract all lines starting with %%## and all lines between \begin{Sinput} and \end{Sinput}, so

%%## Just some text
\begin{Sinput}
> set.seed(271)
> U <- runif(10)
> plot(U, 1-U)
\end{Sinput}
\begin{Sinput}
> plot(qnorm(cbind(U, 1-U)))
\end{Sinput}


I tried to work with sed:

sed -n '/%%##\|\\begin{Sinput}/,/\\end{Sinput}/p' infile.tex # but also contains \begin{example}[foobar]

sed -n '/^%%##\|\\begin{Sinput}/,/\\end{Sinput}/p' infile.tex # but does not contain lines starting with %%##

Note: The above is somewhat derived from this here. Also, a 'two-step' solution (first extracting all lines starting with... and then all chunks) might be possible, too (I just didn't see how and it seems that sed allows to choose several 'patterns' so that seems more elegant).

awk with its range operator (,) works pretty well for this. Tag an extra filter on the end (;) and hey presto.

awk '/^\\begin\{Sinput\}/,/^\\end\{Sinput\}/;/^%%##/' infile.tex
%%## Just some text
\begin{Sinput}
> set.seed(271)
> U <- runif(10)
> plot(U, 1-U)
\end{Sinput}
\begin{Sinput}
> plot(qnorm(cbind(U, 1-U)))
\end{Sinput}

• Thanks a lot. I originally also tried with awk, but couldn't get it to work either. The ; is handy. – Marius Hofert Apr 11 '17 at 21:34
sed -e '/^\\begin{Sinput}/,/^\\end{Sinput}/!{/^%%##/!d}'

perl -lne 'print if /^\Q\begin{Sinput}/ .. /^\Q\end{Sinput}/ or /^%%##/'


The range operator in Perl is ... We use the quote the following text using the \Q so that we don't need to explicitly escape the special characters.

# Result

%%## Just some text
\begin{Sinput}
> set.seed(271)
> U <- runif(10)
> plot(U, 1-U)
\end{Sinput}
\begin{Sinput}
> plot(qnorm(cbind(U, 1-U)))
\end{Sinput}