У меня есть файлы (скажем, infile.tex
) вида
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}
и я хотел бы извлечь все строки, начинающиеся с%%##
ивсе линии между \begin{Sinput}
и \end{Sinput}
, поэтому
%%## 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}
Я пробовал работать с sed
:
sed -n '/%%##\|\\begin{Sinput}/,/\\end{Sinput}/p' infile.tex
# но также содержит\begin{example}[foobar]
sed -n '/^%%##\|\\begin{Sinput}/,/\\end{Sinput}/p' infile.tex
# но не содержит строк, начинающихся с%%##
Примечание: Вышеизложенное в некоторой степени вытекает изэто здесь. Кроме того, возможно также «двухэтапное» решение (сначала извлечение всех строк, начинающихся с ..., а затем всех фрагментов) (я просто не понял, как это сделать, и, похоже, это sed
позволяет выбрать несколько «шаблонов», так что это выглядит более элегантно).
решение1
awk
с его оператором диапазона (,) работает довольно хорошо для этого. Добавьте дополнительный фильтр в конце (;) и вуаля.
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}
решение2
sed -e '/^\\begin{Sinput}/,/^\\end{Sinput}/!{/^%%##/!d}'
perl -lne 'print if /^\Q\begin{Sinput}/ .. /^\Q\end{Sinput}/ or /^%%##/'
Оператор range
в Perl
— ..
. Мы используем кавычки для следующего текста с помощью , \Q
чтобы нам не нужно было явно экранировать специальные символы.
Результат
%%## 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}