以多个步骤处理文件中的所有匹配项并替换某些匹配项

时间:2012-08-20 19:50:58

标签: regex perl

我正在尝试在文件中找到正则表达式的所有匹配项并替换它们。我想分多步找到比赛。例如,我想首先找到两个$ IDENTIFIER_之间的模式,然后在该模式中用$ TWO替换所有$ ONE。

这是我到目前为止所做的:

$entireFile = "Some random text here var_a 4456 var_b var_c 1122 var_d var_e 559 var_f Some random text here ";
my $ONE_="1";
my $TWO_="2";
my $IDENTIFIER_ =  "\\b[a-zA-Z_][a-zA-Z0-9_]*\\b";
my $id1;
my $id2;
my $item;
while ($entireFile =~ m/($IDENTIFIER_)(.*?)($IDENTIFIER_)/g)
{
  $id1  = $1; 
  $item = $2;
  $id2  = $3;
  #Check to see if $item has $ONE and replace with $TWO
  if ($item =~ s/(.*?)$ONE_(.*?)/$1$TWO_$2/g )
  {
    print $id1.$item.$id2."\n" ;
  }
}

打印:

var_c 2222 var_d

我需要帮助的是如何打印文件的其余部分(第一次匹配前的文本,后续匹配之间的文本以及最后一次匹配后的文本)。

2 个答案:

答案 0 :(得分:2)

$entireFile = "Some random text here var_a 4456 var_b".
              " var_c 1122 var_d var_e 559 var_f Some random text here ";
my $ONE_="1";
my $TWO_="2";
my $re_id = qr/\b[a-zA-Z_][a-zA-Z0-9_]*/;
while ($entireFile =~ s/($re_id.*?)$ONE_(.*?$re_id)/$1$TWO_$2/) { } 
print $entireFile;

如果你真的想分两个阶段进行匹配:

$entireFile = "Some random text here var_a 4456 var_b".
              " var_c 1122 var_d var_e 559 var_f Some random text here ";
my ($ONE_, $TWO_) = ("1", "2");
my $re_id = qr/\b[a-zA-Z_][a-zA-Z0-9_]*/;
my $printed=0;
while ($entireFile =~ /($re_id)(.*?)($re_id)/g) {
  my ($id1, $item, $id2) = ($1, $2, $3);
  my ($start, $end, $length) = ($-[0], $+[0], $+[0]-$-[0]);
  if ($printed < $start) {
    print substr($entireFile, $printed, $-[0]-$printed);
    $printed = $start;
  }
  if ($item =~ s/(.*?)$ONE_(.*?)/$1$TWO_$2/g ) { 
    print $id1.$item.$id2."\n" ;
    $printed = $end;
  } else {
    print substr($entireFile, $printed, $length)."\n";
    $printed = $end;
  }
}

答案 1 :(得分:0)

一种方法是使用在替换中执行的函数。

e.g。

$entireFile = "Some random text here var_a 4456 var_b var_c 1122 var_d var_e 559 var_f Some random text here ";
my $ONE_="1";
my $TWO_="2";
my $IDENTIFIER_ =  "\\b[a-zA-Z_][a-zA-Z0-9_]*\\b";

$entireFile =~ s/($IDENTIFIER_)(.*?)($IDENTIFIER_)/$1 . inner_func($2) . $3/egs;
print( $entireFile );

sub inner_func {
    my ( $text ) = @_;

    $text =~ s/$ONE_/$TWO_/g;
    return( $text );
}

/e标志指示替换运算符(s///)执行替换文本,就好像它是代码一样。这对于递归下降解析尤其有用......

如果您在替换时使用/s作为标记,那么您也会告诉搜索和替换处理换行符,就像处理任何其他字符一样 - 使您能够跨行执行此全局替换(如果您已经诽谤首先将整个文件放入变量中。)