중첩된 중괄호를 포함할 수 있는 중괄호 콘텐츠를 분리합니다.

중첩된 중괄호를 포함할 수 있는 중괄호 콘텐츠를 분리합니다.

TeX 파일에는 다음 명령이 있고 \q{aaa}{blablabla}매개변수를 분리하고 싶습니다 blablabla. 나는 sed를 사용하여 그것을 알아 냈습니다.

sed 's/\q{([^}\{])}{([^}\{])}/\2/g'

그리고 그것은 훌륭하게 작동합니다.

문제는있을 때중첩됨패턴에 맞춰 교정기 안쪽 교정기를 유지하고 싶어요. 즉, 만약

\q{aaa}{blablabla \label{BBB}}

원하는 출력은

blablabla \label{BBB}

예를 들어, 계속해서 유지하고 싶은 여러 LaTeX 명령을 상상할 수 있습니다.

\q{aaa}{blablabla \label{BBB} blablabla \includegraphics{ccc.eps} blablabla \cite{somebody_year} blablabla 
\begin{itemize}
\item AAA
\item BBB
\end{itemize}
blablabla to conclude}

이 극단적인 MWE의 예상 결과는 다음과 같습니다.

blablabla \label{BBB} blablabla \includegraphics{ccc.eps} blablabla \cite{somebody_year} blablabla 
\begin{itemize}
\item AAA
\item BBB
\end{itemize}
blablabla to conclude

이러한 예는 매우 (아마도 너무) 복잡한 예입니다. 왜냐하면 내 검색의 최종 목표는 (검토 과정 중) 원고 수정을 최적화하는 것이기 때문입니다.

한 줄로 할 수 있을지는 모르겠지만 sed...

답변1

일반 정규 표현식은 이를 수행할 수 없습니다. 균형 잡힌 괄호가 필요한 언어는 그렇지 않습니다.정규 언어공식적인 의미에서. 따라서 를 사용하면 이 작업을 올바르게 수행할 수 없습니다 sed. 다행스럽게도 Perl과 같은 것들은 실제로 정규 언어에 국한되지 않는 정규식을 제공합니다.

예를 들어, 이 역겨운 행동(SO에 대한 답변에서 수정됨)대괄호와 일치하는 정규식) 당신이 원하는 것을하는 것 같습니다 :

perl -0 -lne 'print "$2\n\n" while m/ \\q\{aaa\} ( \{ ( (?: [^}{]+ | (?1))*+ ) \} )/gx '

입력이 \q{aaa}{blablabla \label{BBB}} \foo{bar}{not this} \q{aaa}{bleh}출력을 준다

blablabla \label{BBB}

bleh

즉, 일치하는 부분 사이에 두 개의 개행 문자가 인쇄됩니다. 위에서 언급했듯이 -0여러 줄의 레이블에서도 작동해야 합니다. 전체 라벨을 얻기 print $2위해 변경할 수도 있습니다 .print $&\q{aaa}{...}

이것이 기본적으로 수행하는 작업은 시작 부분이 \\q\{aaa\}태그의 상수 부분과 일치하고 내부 부분이 (?: [^}{]+ | (?1))*+중괄호가 없는 문자열이거나 첫 번째 캡처링 그룹 항목(대괄호 세트)에서 반복적으로 일치할 수 있는 항목과 일치하는 것입니다. 안의 물건과 일치하는 교정기 쌍.

.../ \\q\{aaa\} ( \{ ( (?: [^}{]+ | (?1))*+ ) \} )/ '
                ^1   ^2               |     ^2   ^1
                |                     |          |
                +---------------------+----------+ 
                        recurse to group 1

두 번째 캡처 그룹은 출력의 일부를 캡처하는 데 사용됩니다.

관련 정보