Я хочу найти все \textbf
в моем .tex
файле и удалить его вместе с его скобками аргументов {}
. Например, я хочу изменить:
\textbf{text}
кtext
\textbf{text \textit{textbis}}
кtext \textit{textbis}
\textbf{\textit{\textls[-5]{textbis}} text}
к\textit{\textls[-5]{textbis}} text
\textbf{\textit{X{textbis}} text}
до\textit{X{textbis}} text
(гдеX
находится разрыв абзаца).
Я пробовал использовать \\textbf\{([^}]*)\}
, \1
но ничего не вышло, потому что сначала он останавливается }
.
решение1
Как уже сказал @David Carlisle, вы не можете сопоставитьпроизвольныйколичество хорошо вложенных {
}
пар. Но с практической точки зрения вы можете знать верхнюю границу максимального уровня вложенности. Если эта граница известна, то можно написать регулярное выражение, распознающее хорошо заключенные в скобки выражения вплоть до максимального уровня вложенности.
Чтобы распознать \texbf{normal text}
(максимальное гнездо = 1), вы можете сделать
\textbf{([^{}]*)}
Запрет {
внутри скобок — это мера предосторожности, чтобы никогда не сопоставлять элементы с уровнем вложенности, превышающим ваш максимальный уровень.
Чтобы сопоставить элементы с максимальным гнездом = 2, можно сделать следующее:
- сначала вы сопоставляете
\\textbf\{
- затем вы сопоставляете любой символ, не являющийся скобкой, с
[^{}]*
- теперь вы, возможно, закончили сопоставление содержимого (фактический уровень вложенности равен 1) и успешно сопоставляете окончание
\}
- или вы можете оказаться в позиции с открытой скобкой. В этом случае вам нужно сопоставить что-то с уровнем вложенности 0, а затем сопоставить закрытую скобку.
Шаги 2, 3 и 4 соответствуют тому, [^{}]*(\{[^{}]*\}[^{}]*)?
что можно повторять, чтобы можно было сопоставлять такие вещи, как\textbf{bla\bla{bla}bla\bla{bla}bla}
Итак, в целом максимальный уровень вложенности = 2 регулярного выражения выглядит следующим образом:
\\textbf\{(([^{}]*(\{[^{}]*\}[^{}]*)?)*)\}
Мы можем экстраполировать схему для максимального гнезда = N больше 2:
\\textbf\{(([^{}]*(\{RN\}[^{}]*)?)*)\}
где
R1 = [^{}]*
RN = ([^{}]*(\{R(N-1)\}[^{}]*)?)*
Так, например, при максимальном гнезде = 3 вы получите
\\textbf\{(([^{}]*(\{(([^{}]*(\{[^{}]*\}[^{}]*)?)*)\}[^{}]*)?)*)\}
чего достаточно, чтобы охватить все случаи, упомянутые вами в вопросе.
решение2
если вы можете использовать нежадные квантификаторы,
заменить\\textbf\{(.*?)\}
\1
Хорошо, как сказал Вернер, это работает только с невложенными командами. Я думаю, что для этого нет простого решения, и это работа парсера.
Если вы все равно хотите сделать это с помощью Regex, вы можете заменить неиспользуемые \textbf
скобки на неиспользуемый символ, а затем в конце удалить \textbf
скобки и заменить символы обратно на скобки:
1) Заменить все закрывающие \textbf
скобки без знаков }
на символ A,
2) Заменить все открывающиеся \textbf
скобки без знаков {
на символ B,
3) Заменить оставшиеся \textbf{
и }
(из \textbf
) ничем,
4) Замените символ A на , {
а символ B на }
@Step 1 и 2:
Шаг 1: }
-> Smybol A, в моем примере на немецком языке ö
:
(?<=(?<!\\textbf)\{(?!.*?\{)).*?\}
Замените это выражение на \1ö
(лучшего решения для этого выражения я не нашел)
Затем выполните Шаг 2: {
-> Символ B, в моем примере немецкийä
(?<!\\textbf)\{(?!.*?\{)
Замените это выражение на ä
.
Повторите эти шаги, сколько у вас вложенных уровней. Затем выполните оставшиеся шаги.
Ну, это скорее макрос регулярного выражения и обходной путь, чем полноценное регулярное выражение, но оно должно работать.