如何在Perl替换中替换匹配前的所有文本?

时间:2020-12-28 21:04:49

I am reading each line of an input file (IN) and printing the line read to an output file (OUT) if the line begins with one of the patterns, say "ab", "cd","ef","gh","ij" etc. The line printed is of form "pattern: 100" or form "pattern: 100:200". I need to replace "pattern" with "myPattern", i.e. print the current line to FILE but replace all the text before the first occurence of ":" with "myPattern". What is the best way to do this?

我正在读取输入文件(IN)的每一行并将行读取打印到输出文件(OUT),如果该行以其中一种模式开头,例如“ab”,“cd”,“ef”,“gh”打印的行是“pattern:100”形式或“pattern:100:200”形式。我需要将“pattern”替换为“myPattern”,即将当前行打印到FILE,但在第一次出现“:”之前用“myPattern”替换所有文本。做这个的最好方式是什么?

Currently I have:

目前我有:

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

I am not sure if substr replacement would help as "pattern" can be either "ab" or"cd" or "ef" or "gh" etc.

我不确定substr替换是否有帮助,因为“pattern”可以是“ab”或“cd”或“ef”或“gh”等。

Thanks! Bi

6 个解决方案

#1


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");
}

My perl is a little rusty, so syntax might not be exact.

我的perl有点生疏,所以语法可能不准确。

edit: Put it in a function for ya.

编辑:把它放在ya的函数中。

#2


Generically, do this like:

通常,这样做:

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}:/;
}

The sort puts the longest ones first, so that if the data has ab:: and both ab and ab: are being substituted, ab: is used instead of ab.

排序首先放置最长的,因此如果数据具有ab ::并且ab和ab都被替换,则使用ab:而不是ab。

#3


Perl's substitution operator by default (a) uses the first match, (b) only replaces one match and (c) returns true if a replacement was made and false if it wasn't.

默认情况下Perl的替换运算符(a)使用第一个匹配,(b)仅替换一个匹配,(c)如果替换则返回true,否则返回false。

So:

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

Should work for you. Note that because of short-circuiting, only one substitution will be made.

应该适合你。请注意,由于短路,只会进行一次替换。

#4


while ( <IN> )
{ 
  s/^pattern:/myPattern:/;
  print OUT
}

#5


This might be what you want:

这可能是你想要的:

$expr = "^(ab)|(cd)|(ef)|(gh)|(ij)";
while (<IN>)
{
    if (/$expr:/)
    {
        s/$expr/$myPattern/;
        print FILE;
    }
}

#6


The shortest way to do what you ask above is to re-use your code, but include a substitution.

执行上述要求的最短路径是重用代码,但包含替换。

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

Any of the left hand side patterns will be replaced. If the left hand side does not match, nothing will be printed.

任何左侧图案都将被替换。如果左侧不匹配,则不会打印任何内容。

#1


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");
}

My perl is a little rusty, so syntax might not be exact.

我的perl有点生疏,所以语法可能不准确。

edit: Put it in a function for ya.

编辑:把它放在ya的函数中。

#2


Generically, do this like:

通常,这样做:

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}:/;
}

The sort puts the longest ones first, so that if the data has ab:: and both ab and ab: are being substituted, ab: is used instead of ab.

排序首先放置最长的,因此如果数据具有ab ::并且ab和ab都被替换,则使用ab:而不是ab。

#3


Perl's substitution operator by default (a) uses the first match, (b) only replaces one match and (c) returns true if a replacement was made and false if it wasn't.

默认情况下Perl的替换运算符(a)使用第一个匹配,(b)仅替换一个匹配,(c)如果替换则返回true,否则返回false。

So:

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

Should work for you. Note that because of short-circuiting, only one substitution will be made.

应该适合你。请注意,由于短路,只会进行一次替换。

#4


while ( <IN> )
{ 
  s/^pattern:/myPattern:/;
  print OUT
}

#5


This might be what you want:

这可能是你想要的:

$expr = "^(ab)|(cd)|(ef)|(gh)|(ij)";
while (<IN>)
{
    if (/$expr:/)
    {
        s/$expr/$myPattern/;
        print FILE;
    }
}

#6


The shortest way to do what you ask above is to re-use your code, but include a substitution.

执行上述要求的最短路径是重用代码,但包含替换。

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

Any of the left hand side patterns will be replaced. If the left hand side does not match, nothing will be printed.

任何左侧图案都将被替换。如果左侧不匹配,则不会打印任何内容。