Подстановки в строке между начальным регулярным выражением и конечным регулярным выражением

awk '/[0-9]+ of [0-9]+ DOCUMENTS/{g++} { print $0 > g".txt"}' file

Пользователям OSX потребуется gawk, так как встроенный awk приведет к ошибке, например awk: illegal statement at source line 1

Ruby (1.9 +)

#!/usr/bin/env ruby
g=1
f=File.open(g.to_s + ".txt","w")
open("file").each do |line|
  if line[/\d+ of \d+ DOCUMENTS/]
    f.close
    g+=1
    f=File.open(g.to_s + ".txt","w")
  end
  f.print line
end
1
задан zdim 18 April 2019 в 19:03
поделиться

2 ответа

Осложнение, что вам нужна глобальная замена, но только внутри шаблонов маркеров, может быть обработано путем захвата этой подстроки и выполнения регулярного выражения в ней в заменяющей части

my $s = q(a1b x and x c2d x more x  a22b x again x c33d x and x); 

$s =~ s/a.*?b\K(.*?)(?=c.*?d)/$1=~s{x}{y}gr/eg;

say $s;

Я использую \K после левой шаблон маркера (a.*?b) для отбрасывания предыдущих совпадений и просмотра шаблона правого маркера (c.*?d), чтобы не копировать их вокруг, но для простоты вы можете захватить их и использовать числовые переменные ([116 ]) для них в замен.

Рассмотрите возможность захвата правого маркера (вместо предвкушения), если шаблон повторяется; тогда для дополнительной копии данных подшаблон не сканируется повторно, и все регулярные выражения чище и в принципе безопаснее (может ли правый маркер содержать левый маркер?). Это усложняет замену, где $2 нужно сохранить перед новым регулярным выражением, так как оно в нем сбрасывается.

Обратите внимание на модификатор /r в регулярном выражении заменяющей части: кроме того, что он очень удобен, он также позволяет нам использовать s/// для переменной $1, что в противном случае мы не могли бы сделать, поскольку она только для чтения. [1116 ]

Если это часть более сложной обработки регулярных выражений, обратите внимание, что упреждение является утверждением нулевой ширины , поэтому движок не использует этот шаблон и не пропускает его. Это имеет значение, если весь шаблон повторяется: если возможно, что правый маркер содержит левый маркер, вы должны захватить его, чтобы двигатель прошел мимо него для следующего матча, чтобы левый маркер был первым для него.


Это работает с переменными для шаблонов маркеров, которые вы любезно используете

my $start = qr/a.*?b/;
my $end   = qr/c.*?d/;

my $s = q(a1b x and x c2d x more x  a22b x again x c33d x and x); 

$s =~ s/$start\K (.*?) (?=$end)/ $1 =~ s{x}{y}gr /egx;

say $s;

, где я размечал шаблоны для удобства чтения, благодаря /x. Это печатает

a1b y and y c2d x more x  a22b y again y c33d x and x
0
ответ дан zdim 18 April 2019 в 19:03
поделиться

Вы можете использовать /e, модифицированный для выполнения кода (для каждого совпадения отдельно) для генерации строки замены:

use strict;
use warnings;

my $start_regex  = qr/a.*?b/;
my $end_regex    = qr/c.*?d/;
my $string = 'a1b x c2d x a345b qqxxxc678d xx abxcd';

$string =~ s/($start_regex)(.*?)($end_regex)/ my ($start_match, $middle_match, $end_match) = ($1, $2, $3); $middle_match =~ s!x!y!g; $start_match . $middle_match . $end_match /eg;

print $string, "\n";

Распечатает

a1b y c2d x a345b qqyyyc678d xx abycd

Обратите внимание на альтернативу разделитель регулярных выражений s!!! во внутреннем регулярном выражении.

Важно хранить $1, $2 и $3 внешнего соответствия регулярному выражению во временных переменных, так как они будут потеряны, когда вы выполните другое регулярное выражение в коде замены.

0
ответ дан Silvar 18 April 2019 в 19:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: