Regex найти и заменить промежуточную среду латекса - PullRequest
0 голосов
/ 17 февраля 2019

Я пытаюсь найти регулярное выражение для использования при поиске и замене, чтобы найти все символы '(', используемые в среде выравнивания. Пример текста:

Lorem Ipsum Lorem Ipsum Lorem Ipsum 
Lorem Ipsum Lorem Ipsum (Lorem Ipsum Lorem Ipsum )
Lorem Ipsum Lorem Ipsum Lorem Ipsum Lorem Ipsum 
\begin{align}
\frac{d_l}{2}< |\epsilon_H(g(m))| <\frac{d_r}{2} 
\frac{d_l}{2}< |\epsilon_H(g(m))| <\frac{d_r}{2} 
\end{align}
Lorem Ipsum Lorem Ipsum Lorem Ipsum 
Lorem Ipsum Lorem Ipsum Lorem Ipsum 

Затем я хочучтобы найти все '(' внутри \begin{align} и \end{align}, а НЕ внутри основной части текста. У меня пока есть регулярное выражение:

(?<=\{align\})\s(.*)\s(.*)\s(?=\\end\{align\})

, но это находит ВСЕ текст внутриокружение, а не отдельные экземпляры '('.

(Причина этого в том, что мне нужно просмотреть весь документ и изменить все '(' внутри уравнений на '\left(', и яне хочу менять скобки, встречающиеся в тексте, который может быть использован.)

Ответы [ 2 ]

0 голосов
/ 17 февраля 2019

Используйте оператор диапазона (..) в скалярном контексте, то есть как триггер, чтобы изолировать блоки, над которыми вы хотите работать.

#!/usr/bin/perl
use strict;
use warnings;

while (<STDIN>) {
    if (/^\\begin\{align\}/../^\\end\{align\}/) {
        # replace all occurences of "(" with "\left("
        s/\(/\\left(/g;
    }
    print;
}

exit 0;

Тестовый запуск с заданным вами текстом:

$ perl dummy.pl <dummy.txt
Lorem Ipsum Lorem Ipsum Lorem Ipsum
Lorem Ipsum Lorem Ipsum (Lorem Ipsum Lorem Ipsum )
Lorem Ipsum Lorem Ipsum Lorem Ipsum Lorem Ipsum
\begin{align}
\frac{d_l}{2}< |\epsilon_H\left(g\left(m))| <\frac{d_r}{2}
\frac{d_l}{2}< |\epsilon_H\left(g\left(m))| <\frac{d_r}{2}
\end{align}
Lorem Ipsum Lorem Ipsum Lorem Ipsum
Lorem Ipsum Lorem Ipsum Lorem Ipsum

Или в виде однострочного:

$ perl <dummy.txt -pe 's/\(/\\left(/g if (/^\\begin\{align\}/../^\\end\{align\}/)'
...
\frac{d_l}{2}< |\epsilon_H\left(g\left(m))| <\frac{d_r}{2}
\frac{d_l}{2}< |\epsilon_H\left(g\left(m))| <\frac{d_r}{2}
...

Если обнаружение блока слишком строго, т. Е. В вашем реальном документе \begin и \end не находятся в началезатем введите следующую строку без ^ (каретка):

 if (/\\begin\{align\}/../\\end\{align\}/) {
0 голосов
/ 17 февраля 2019

Существует два метода выполнения данной задачи.Один из них запускает совпадение с \\begin{align}, а второй - сигнализирует о прекращении сопоставления ( сразу после столкновения с \\end{align}.

. Первый шаг можно выполнить с помощью токена \G, а второй - задание.для ограничительного соответствия или закаленного - [^(].

(?:\\begin{align}|\G(?!\A))(?:(?!\\end{align})[^(])*\K\(

См. живую демонстрацию здесь

Код Perl:

my $regex = qr/(?:\\begin{align}|\G(?!\A))(?:(?!\\end{align})[^(])*\K\(/p;
my $subst = '\\\\left(';
my $result = $str =~ s/$regex/$subst/rg;

См. живая демонстрация здесь

Распределение регулярных выражений:

  • (?: Начало группы без захвата
    • \\begin{align} Матч \begin{align} буквально
    • | Или
    • \G(?!\A) Начать матч с того места, где заканчивается предыдущий матч
  • ) Конец группы без захвата
  • (?: Начало NCG
    • (?!\\end{align}) Пока мы не достигнем \end{align}
    • [^(] Попробуйте сопоставить не-( символ
  • )* Конец NCG, повторите как можно больше
  • \K\( Сбросьте совпавшую часть и попробуйте сопоставить (

Однострочник:

perl -0777 -i.bak -pe 's~(?:\\begin\{align}|\G(?!\A))(?:(?!\\end\{align})[^(])*\K\(~\\left(~g;' file
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...