Как я могу удалить символы между ‹и› в Perl?

Мне нужно написать сценарий Perl для чтения в файле и удаления всего внутри ‹>, даже если они находятся в разных строках. То есть, если ввод:

Hello, world. I <enjoy eating
bagels. They are quite tasty.
I prefer when I ate a bagel to
when I >ate a sandwich. <I also
like >bananas.

Я хочу, чтобы результат был:

Hello, world. I ate a sandwich. bananas.

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

Изменить: также требуется более 1 экземпляра ‹>


person rlbond    schedule 10.04.2009    source источник


Ответы (4)


Вы можете попробовать модуль Perl Text :: Balanced, являющийся частью ядра распределение. Думаю, тебе это поможет. Как правило, нужно избегать использования регулярных выражений для подобных вещей, ЕСЛИ в тематическом тексте, вероятно, будет внутренний набор разделителей, он может стать очень беспорядочным.

person Danny    schedule 10.04.2009
comment
Хороший совет, но в данном случае он не нужен. Обязательно буду иметь в виду. - person rlbond; 11.04.2009

В Perl:

#! /usr/bin/perl   
use strict;

my $text = <>;
$text =~ s/<[^>]*>//g;
print $text;

Регулярное выражение заменяет все, что начинается с ‹до первого> (включительно), и ничего не заменяет. G является глобальным (более одного раза).

РЕДАКТИРОВАТЬ: включены комментарии от Хайнека и хаоса

person Gene Gotimer    schedule 10.04.2009
comment
Это немного неэффективно. Чтобы разделить его и снова присоединиться. perl -0777 -pe 's / ‹[^›] * ›// gm' - person Hynek -Pichi- Vychodil; 10.04.2009
comment
модификатор / m не помогает. Это означает «рассматривать как многострочную», т.е. сопоставлять ^ и $ в символах новой строки, а не «это многострочный». / s, рассматриваемый как одна строка, на самом деле больше того, что вам нужно, но вам это не нужно, потому что ваш шаблон не связан с пробелами. - person chaos; 10.04.2009
comment
Я бы поместил обе угловые скобки в класс отрицательных символов: s / ‹[^‹ ›] *› // g. В противном случае вы могли бы сопоставить «отсюда‹ здесь », что, вероятно, не то, что вам нужно. - person Alan Moore; 10.04.2009
comment
Очень полезно. Ответ Хаоса, однако, более приспособлен к многосимвольным разделителям, I.E. с использованием . и / s вместо [^ (delimiter)] +1 за отличный совет. - person rlbond; 11.04.2009

Неэффективный однострочный способ

perl -0777 -pe 's/<.*?>//gs'

то же, что и программа

local $/;
my $text = <>;
s/<.*?>//gs;
print $text;

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

perl -pe 'if ($a) {(s/.*?>// and do {s/<.*?>//g; $a = s/<.*//s;1}) or $_=q{}} else {s/<.*?>//g; $a = s/<.*//s}'

то же, что и программа

my $a;
while (<>) {
    if ($a) {
        if (s/.*?>//) {
            s/<.*?>//g;
            $a = s/<.*//s;
        }
        else { $_ = q{} }
    }
    else {
        s/<.*?>//g;
        $a = s/<.*//s;
    }
    print;
}
person Hynek -Pichi- Vychodil    schedule 10.04.2009
comment
Как отмечалось в ответе CoverosGene, / m не является необходимым или полезным. - person chaos; 10.04.2009

person    schedule
comment
Если ваша строка выглядит так: ‹abc ‹def› ghi›, ваше регулярное выражение оставляет «ghi› ». Если вложенные или экранированные скобки и другие извращенные случаи никогда не встречаются, регулярное выражение в порядке. Чтобы справиться с извращенными случаями, используйте Text :: Balanced, даже если интерфейс странный. - person daotoad; 10.04.2009