Entfernen Sie die Funktionalität eines Makros über einen regulären Ausdruck

Entfernen Sie die Funktionalität eines Makros über einen regulären Ausdruck

Ich möchte alles \textbfin meiner .texDatei finden und es zusammen mit den Klammern löschen {}. Ich möchte beispielsweise Folgendes ändern:

  1. \textbf{text}Zutext

  2. \textbf{text \textit{textbis}}Zutext \textit{textbis}

  3. \textbf{\textit{\textls[-5]{textbis}} text}Zu\textit{\textls[-5]{textbis}} text

  4. \textbf{\textit{X{textbis}} text}zu \textit{X{textbis}} text(wobei Xein Absatzumbruch ist).

Ich habe versucht, \\textbf\{([^}]*)\}es zu verwenden \1, aber es hat nicht funktioniert, weil es zuerst stoppt }.

Antwort1

Wie bereits von @David Carlisle erwähnt, können Sie nicht mithalten mit einemwillkürlichAnzahl gut verschachtelter { }Paare. Aus praktischer Sicht kennen Sie jedoch möglicherweise eine Obergrenze für die maximale Verschachtelungsebene. Wenn diese Grenze bekannt ist, ist es möglich, einen regulären Ausdruck zu schreiben, der gut eingeklammerte Ausdrücke bis zur maximalen Verschachtelungsebene erkennt.

Um zu erkennen \texbf{normal text}(max nest = 1) können Sie

\textbf{([^{}]*)}

Das Verbot {innerhalb der Klammern ist eine Vorsichtsmaßnahme, um sicherzustellen, dass niemals Dinge mit einer Verschachtelungsebene übereinstimmen, die höher ist als Ihr Maximum.

Um Dinge mit max. Nest = 2 abzugleichen, können Sie Folgendes tun:

  1. zuerst passt du\\textbf\{
  2. dann gleichen Sie alle Zeichen außer Klammern mit[^{}]*
  3. jetzt haben Sie möglicherweise den Inhalt abgeglichen (die tatsächliche Verschachtelungsebene ist 1) und können glücklicherweise die Endung abgleichen\}
  4. oder Sie könnten sich an einer Stelle mit einer öffnenden Klammer befinden. In diesem Fall müssen Sie etwas mit der Verschachtelungsebene 0 abgleichen und dann die schließende Klammer abgleichen.

Die Schritte 2, 3 und 4 entsprechen denen [^{}]*(\{[^{}]*\}[^{}]*)?, die wiederholt werden können, so dass Sie Dinge wie\textbf{bla\bla{bla}bla\bla{bla}bla}

Insgesamt sieht der reguläre Ausdruck mit der maximalen Verschachtelungsebene = 2 so aus:

\\textbf\{(([^{}]*(\{[^{}]*\}[^{}]*)?)*)\}

Wir können das Schema für max. Nest = N größer als 2 extrapolieren:

\\textbf\{(([^{}]*(\{RN\}[^{}]*)?)*)\}

Wo

R1 = [^{}]*
RN = ([^{}]*(\{R(N-1)\}[^{}]*)?)*

So erhalten Sie beispielsweise mit max nest = 3

\\textbf\{(([^{}]*(\{(([^{}]*(\{[^{}]*\}[^{}]*)?)*)\}[^{}]*)?)*)\}

Dies reicht aus, um alle in der Frage genannten Fälle abzudecken.

Antwort2

wenn Sie nicht-gierige Quantifizierer verwenden können,

ersetzen \\textbf\{(.*?)\}mit\1

Ok, wie Werner erwähnt hat, funktioniert dies nur mit nicht verschachtelten Befehlen. Ich denke, dafür gibt es keine einfache Lösung und es ist eine Aufgabe des Parsers.

Wenn Sie es trotzdem mit Regex machen möchten, können Sie die nicht- \textbf-Klammern durch ein nicht verwendetes Symbol ersetzen und am Ende die \textbf-Klammern entfernen und die Symbole wieder in Klammern ändern:

1) Ersetzen Sie alle schließenden \textbfKlammern außer - }durch das Symbol A.

2) Ersetzen Sie alle öffnenden \textbfKlammern außer - {durch das Symbol B,

3) Ersetzen Sie das verbleibende \textbf{und }(von \textbf) durch nichts,

4) Ersetzen Sie Symbol A durch {und Symbol B durch }


@Schritt 1 und 2:

Schritt 1: }-> Symbol A, in meinem Beispiel deutsch ö:

(?<=(?<!\\textbf)\{(?!.*?\{)).*?\}

Ersetzen Sie diesen Ausdruck durch \1ö(ich habe keine bessere Lösung für diesen Ausdruck gefunden)


Dann führen Sie Schritt 2 aus: {-> Symbol B, in meinem Beispiel deutschä

(?<!\\textbf)\{(?!.*?\{)

Ersetzen Sie diesen Ausdruck durch ä.


Wiederholen Sie diese Schritte, so viele verschachtelte Ebenen Sie haben. Führen Sie dann die restlichen Schritte aus.


Nun, dies ist eher ein Regex-Makro und ein Workaround als ein solider Regex, aber es sollte funktionieren.

verwandte Informationen