텍스트에서 특정 라텍스 명령과 다음 닫는 대괄호를 제거합니다.

텍스트에서 특정 라텍스 명령과 다음 닫는 대괄호를 제거합니다.

텍스트에서 특정 latex 명령을 제거하고 그 뒤에 닫는 대괄호를 추가하되 대괄호 안에 텍스트를 유지하려면 어떻게 해야 합니까? 다음 예에서 제거할 명령은 입니다 \edit{<some staff>}. 제거해야 하며 \edit{변경 되지 않은 상태로 유지되어야 합니다.}<some staff>

SED, AWK, Perl 또는 해당 작업을 수행할 수 있는 모든 것을 자유롭게 제안하십시오.

무의미한 예:

We \edit{Introduce a} model for analyzing \emph{data} from various
experimental designs, \edit{such as paired or \url{http://www/}
longitudinal; as was done 1984 by NN \cite{mycitation} and by NNN
\cite{mycitation2}}.

\command{smth}명령문 내의 양식에는 하나 이상의 Latex 명령이 있을 수 있습니다 \edit{}. \command{smth} 그대로 남아야 한다

산출:

We Introduce a model for analyzing \emph{data} from various
experimental designs, such as paired or \url{http://www/}
longitudinal; as was done 1984 by NN \cite{mycitation} and by NNN
\cite{mycitation2}.

추신. 내 텍스트 파일에 많은 작은 수정을 가할 것입니다. 공동작업자가 볼 수 있도록 이러한 편집 내용을 강조표시하고 싶습니다. 하지만 강조 표시를 모두 제거하고 텍스트를 리뷰어에게 보내고 싶습니다.

이 질문은 원래 다음에서 제기되었습니다.AWK/SED는 텍스트에서 특정 Latex 명령을 제거하고 그 뒤에 닫는 대괄호를 추가합니다.. 예를 들어 너무 부드럽습니다.

답변1

\edit{...}다음은 최대 한 수준의 명령을 사용하여 간단한 경우에 작동하는 명령입니다.

perl -00 -lpe 's,\\edit\{( (?: [^}\\]* | \\[a-z]+\{[^}]*\} )+ )\},$1,xg'

중간에 (?: [^}\\]* | \\[a-z]+\{[^}]*\} )+대안이 있습니다 . [^}\\]*닫는 중괄호나 백슬래시(일반 텍스트) 없이 문자열을 일치시키고 \\[a-z]+\{[^}]*\}백슬래시, 소문자 및 일치하는 중괄호 쌍(예: )이 있는 문자열 \url{whatever...}을 일치시킵니다. 그룹화는 (?:...)+이러한 대체와 외부 대괄호 캡처를 반복하므로 일치 항목을 내부 부분으로만 대체할 수 있습니다 \edit{...}.

-00Perl은 한 번에 한 문단씩 입력을 처리하고 문단을 빈 줄로 구분하도록 지시합니다. 여러 단락에 걸쳐 있는 태그를 처리해야 하는 경우 -0777전체 입력을 한 번에 처리하도록 이를 변경합니다( -0텍스트 파일에 대한 입력이 없기 때문에 NUL로 구분된 입력에도 작동함).

귀하의 예에서는 다음과 같이 작동하는 것 같습니다.

We Introduce a model for analyzing \emph{data} from various
experimental designs, such as paired or \url{http://www/}
longitudinal; as was done 1984 by NN \cite{mycitation} and by NNN
\cite{mycitation2}.

그러나 두 가지 수준의 명령이 포함된 입력의 경우 (예상대로) 실패합니다 \edit{...}.

Some \edit{\somecmd{\emph{nested} commands} here}.

이동 :

Some \somecmd{\emph{nested} commands here}.

(잘못된 닫는 중괄호가 제거됨)


균형 괄호를 다루는 것은 실제로 약간 까다롭습니다. 예를 들어 다음 질문에서 논의됩니다. Perl 정규식: 중첩된 대괄호 일치.

답변2

간결하지는 않지만 중첩된 명령을 사용하면 잘 수행되는 Python 기반 솔루션이 있습니다.

def command_remove(tex_in, keywords):
    # Romove command with curly bracket
    # keywords: "hl textbf" mean removing \hl{} and \textbf{}
    pattern = '\\\\(' + keywords.replace(' ', '|') + '){'
    commands = re.finditer(pattern, tex_in)
    idxs_to_del = [] # The index of }
    for command in commands:
        stack = 0
        current_loc = command.span()[1]
        while not (tex_in[current_loc] == '}' and stack == 0):
            if tex_in[current_loc] == '}':
                stack = stack - 1
            if tex_in[current_loc] == '{':
                stack = stack + 1
            current_loc = current_loc + 1
        idxs_to_del.append(current_loc)

    idxs_to_del = sorted(idxs_to_del, reverse=True) # sort
    tex_list = list(tex_in)
    for idx in idxs_to_del:
        tex_list.pop(idx) # remove }

    tex_out = ''.join(tex_list)
    tex_out = re.sub(pattern, '', tex_out) # remove \xxx{
    return tex_out

정규식을 통해 대상 명령을 찾은 다음 스택을 통해 닫는 괄호의 위치를 ​​찾습니다. 을 위한 tex_out = command_remove(tex_in, "revise textbf"):tex_in

\hl{Can you} \revise{can a \textbf{can} as a \emph{canner} can} can a can?

우리는 얻을 것이다 tex_out:

\hl{Can you} can a can as a \emph{canner} can can a can?

자세한 내용(예: 명령줄 실행)은 다음을 참조하세요.latex_command_delete.

답변3

\edit{...}LaTeX 명령(다른 쌍을 의미)을 사용하여 s를 처리 하려면 정규식에서 재귀를 처리하는 기능을 {...}사용할 수 있습니다 .perl

perl -pe 's{\\edit(\{((?:[^{}]++|(?1))*)\})}{$2}g' file

(?1)첫 번째 쌍의 정규 표현식이 호출되고 여기 (...)에 해당 쌍과 일치하는 정규 표현식이 있습니다 {...}.

(이스케이프된 중괄호나 \verb주석은 여기서 처리되지 않으며 s가 여러 줄에 걸쳐 있지 않다고 가정합니다 \edit{...}. 필요한 경우 모든 줄을 상당히 쉽게 추가할 수 있습니다.)

관련 정보