Удаление операторов в фигурных скобках, содержащих вложенные фигурные скобки внутри.

Вопрос или проблема

Типичная проблема в LaTeX:

\SomeStyle{\otherstyle{this is the \textit{nested part} some more text...}}

Теперь я хочу удалить все \SomeStyle{...}, но не содержимое. Содержимое содержит вложенные скобки. Строка выше должна стать:

\otherstyle{this is the \textit{nested part} some more text...}

Вопросы:

  1. Предлагает ли какой-либо редактор LaTeX способ сделать это?
  2. Какой редактор/скрипт делает это?
  3. Как это сделать с помощью sed? [🤓]

Мое решение — это bash-скрипт, использующий sed.

  1. подготовить текст: отметить строку замены с помощью ASCII звонка, добавить новую строку после каждой скобки
  2. цикл: найти { -> добавить X в холд-спейс, найти } -> удалить X из холд-спейса, холд-спейс пуст -> удалить закрывающую }
  3. восстановить новые строки и ASCII звонок в предыдущий вид

Скрипт работает, но не справляется с:
\badstyle{w}\badstyle{o}\badstyle{r}\badstyle{d}
Он станет:
wo}rd}

Ветвление к :f, кажется, не работает.

F=$(sed 's|\\|\\\\|g;s|{|\\{|g' <<< "$1"  )

# отметить все строки для удаления с помощью ASCII звонка и новой строки
# добавить новую строку после каждой { и }
SEDpre="
s|""$F"'|\a%\n|g

s|\{|\{\n|g
s|\}|\}\n|g
'


SEDpost="
:a;N;$!ba;
s|\a%\n||g

s|\{\n|\{|g
s|\}\n|\}|g
"

# подсчитать скобки
SED='
/\a%/{
:a
        n
:f
        /\{/{x;s|$|X|;x;ba}
        /\}/{x;
                s|X||;
                /^$/{x;bb}
                x
                ba
            }
}
b
:b  
/\}/{   
    s|\}||;
    N;
    s|\n||;
    /\a%/bf
     }
'

sed -r -E  "$SEDpre"  "$2"  | sed -rE "$SED"  | sed -rE "$SEDpost" 

Типичный подход — использовать рекурсивную возможность регулярных выражений perl:

perl -0777 -pe 's/\\SomeStyle(\{((?:(?1)|[^{}])*)\})/$2/gs' file.tex

(добавьте опцию -i для редактирования файла на месте i).

Выше (?1) подобно вставке регулярного выражения в первую пару (...), так что (\{((?:(?1)|[^{}])*)\}) на этой позиции.

Вот возможный механизм для sed. Для простоты предполагаем, что нет символов подчеркивания, поэтому мы можем использовать один в качестве маркера. Это аналогично вашему ASCII звонку. Мы вставляем маркер в начало строки и перемещаем его символ за символом до конца строки. Каждый раз, когда он перемещается через {, мы добавляем знак + в начало строки в качестве счетчика. Каждый раз, когда он перемещается через }, мы удаляем знак + из начала. Если у нас больше нет знаков +, значит, мы сбалансировали скобки и можем применить замену, необходимую до маркера.

В случае, если строка уже начинается с +, мы начинаем с добавления !! в начало и удаляем это в конце.

sed '
 s/^/!!_/
:a
 /_\(.\)/{
   s//\1_/
   /{_/{
     s/^/+/
   }
   /}_/{
     /^+/!{
       s/^/mismatch{}/
       b
     }
     s///
     /^!!/b b
   }
   b a
 }
 # движения сюда, если _ в конце строки
:b
 # фиктивный переход на очистку, чтобы можно было обнаружить, если s выполнено
 t c
:c
 s/\\SomeStyle{\(.*\)}_/\1_/
 s/\\badstyle{\(.*\)}_/\1_/
 # повторяем, чтобы выполнить глобально на строке
 t a
 s/^!!//
 s/_$//
'

Ответ или решение

Вопрос о том, как удалить определенные конструкции в LaTeX, сохраняя при этом содержимое, представляет собой интересную задачу, особенно когда дело касается вложенных фигурных скобок. В данном случае речь идет о необходимости убрать оболочку команды \SomeStyle{...}, не затрагивая находящееся внутри содержимое, которое может включать другие команды с вложенными скобками.

Теоретическая часть

В TeX и LaTeX фигурные скобки {} используются для определения границ аргументов команд. Например, конструкция \SomeStyle{...} означает применение стиля \SomeStyle ко всему, что заключено в фигурные скобки. Задача заключается в удалении этой оболочки, но без изменения вложенного содержимого.

Для решения этой задачи первоочередной проблемой является обработка вложенных фигурных скобок. Инструменты обработки текстов, такие как sed и perl, предоставляют мощные средства для поиска и замены строк на основе регулярных выражений, но их подходы существенно различаются. В частности, perl поддерживает рекурсивные регулярные выражения, которые позволяют более удобно работать со вложенными структурами, в отличие от sed, где требуется более сложное манипулирование текстом для достижения аналогичного эффекта.

Пример решения и его применение

Перейдём к рассмотрению практических решений данной задачи с использованием как perl, так и sed.

Использование Perl

Perl однозначно выделяется среди текстовых редакторов благодаря поддержке рекурсивных регулярных выражений. Вот пример команды, которая достигает цели:

perl -0777 -pe 's/\\SomeStyle(\{((?:(?1)|[^{}])*)\})/$2/gs' file.tex

На этом примере можно увидеть мощь рекурсивных регулярных выражений:

  1. (?1) — это рекурсивная ссылка на первое подвыражение в круглых скобках, (\{((?:(?1)|[^{}])*)\}), что позволяет обработать любое количество вложенных фигурных скобок.

  2. Опция -0777 объединяет всю обработку файла в одно единственное строковое выражение (захватывает всю строку).

Этот подход позволяет "развернуть" любую конструкцию верхнего уровня типа \SomeStyle{...} с множеством вложенных скобок.

Пример с использованием Sed

Поскольку sed не поддерживает рекурсивные регулярные выражения, решение оказывается более сложным и требует пошагового манипулирования как исходным текстом, так и дополнительными маркерами:

sed '
 s/^/!!_/
:a
 /_\(.\)/{
   s//\1_/
   /{_/{
     s/^/+/
   }
   /}_/{
     /^+/!{
       s/^/ошибка{}/
       b
     }
     s///
     /^!!/b b
   }
   b a
 }
:b
 # Переход после обработки каждой строки
 # Удаляем команду \SomeStyle, заменяя ее содержимым
 s/\\SomeStyle{\(.*\)}_/\1_/
 # Повторяем для каждой вложенной строки
 t a
 s/^!!//
 s/_$//
' file.tex

Здесь используются специальные символы (например, _) для перемещения по строке и + как счетчик, обрабатывающий каждое появление { и }. Как только счетчик становится пустым, можно выполнить необходимую подстановку.

Заключение

Эти решения показывают, как можно эффективно использовать скрипты и текстовые редакторы для обработки сложных строковых конструкций. В зависимости от сложности задачи и доступных инструментов выбор между perl и sed может варьироваться. Perl предпочтителен в случаях, когда требуется удобство и мощь рекурсивных выражений, тогда как sed может использоваться, когда доступ к perl затруднён или необходимость обработки текста возникает в контексте Unix-скриптов, где sed является стандартом.

Таким образом, каждой из подходов имеет свои плюсы и минусы, и выбор инструмента должен основываться на конкретных технических требованиях проекта и опыте разработчика.

Оцените материал
Добавить комментарий

Капча загружается...