Как я могу заменить весь текст перед соответствием в замене Perl? - PullRequest
3 голосов
/ 16 июня 2009

Я читаю каждую строку входного файла (IN) и печатаю строку, считанную в выходной файл (OUT), если строка начинается с одного из шаблонов, скажем «ab», «cd», «ef», "gh", "ij" и т. д. Напечатанная строка имеет форму "pattern: 100" или form "pattern: 100: 200". Мне нужно заменить «pattern» на «myPattern», то есть вывести текущую строку в FILE, но заменить весь текст до первого появления «:» на «myPattern». Каков наилучший способ сделать это?

В настоящее время у меня есть:

while ( <IN> )
{ 
    print FILE if /^ab:|^bc:|^ef:|^gh:/;
}

Я не уверен, поможет ли замена substr, поскольку "pattern" может быть либо "ab", либо "cd", либо "ef", либо "gh" и т. Д.

Спасибо! Bi

Ответы [ 6 ]

3 голосов
/ 16 июня 2009

Обычно делайте это следующим образом:

my %subst = ( 'ab' => 'newab', 'bc' => 'newbc', 'xy' => 'newxy' );
my $regex = join( '|', map quotemeta, sort { length($b) <=> length($a) } keys %subst );
$regex = qr/^($regex):/;

while ( <IN> ) {
    print FILE if s/$regex/$subst{$1}:/;
}

Сортировка ставит самые длинные на первое место, так что если в данных подставляются ab :: и заменяются ab и ab: ab, вместо ab используется *: 1004 *

1 голос
/ 16 июня 2009

Оператор подстановки Perl по умолчанию (a) использует первое совпадение, (b) заменяет только одно совпадение и (c) возвращает true, если замена была сделана, и false, если она не была.

Итак:

while ( <IN> )
{ 
    if (s/<pattern1>:/<replace1>/ ||
        s/<pattern2>:/<replace2>/) {
       print FILE;
    }
}

Должно работать на вас. Обратите внимание, что из-за короткого замыкания будет произведена только одна замена.

0 голосов
/ 16 июня 2009

Самый короткий способ сделать то, что вы просите, - это повторно использовать ваш код, но включить подстановку.

while ( <IN> )
{ 
    print FILE if s/^(ab|bc|ef|gh):/MyPattern:/;
}

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

0 голосов
/ 16 июня 2009
sub replacer {

    $line = shift;
    $find = shift;
    $replace = shift;

    $line =~ /([^:]+):/
    if ($1 =~ /$find/) { 
         $line =~ s/([^:]+):/$replace/ ;
         return $line;      
    }
    return ;

}

while (<IN>)
{
    print OUT replacer ($_,"mean","variance");
    print OUT replacer ($_,"pattern","newPattern");
}

Мой Perl немного ржавый, поэтому синтаксис может быть не точным.

edit : Поместите его в функцию для вас.

0 голосов
/ 16 июня 2009

Это может быть то, что вы хотите:

$expr = "^(ab)|(cd)|(ef)|(gh)|(ij)";
while (<IN>)
{
    if (/$expr:/)
    {
        s/$expr/$myPattern/;
        print FILE;
    }
}
0 голосов
/ 16 июня 2009
while ( <IN> )
{ 
  s/^pattern:/myPattern:/;
  print OUT
}
...