0

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

这是我到目前为止所拥有的:

$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

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

4

2 回答 2

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;
  }
}
于 2012-08-20T20:03:22.787 回答
0

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

例如

$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在替换时使用作为标志,您还告诉搜索和替换将换行符视为任何其他字符 - 使您能够跨行执行此全局替换(如果您已将整个文件放入您的变量中第一名)。

于 2012-08-20T21:06:17.350 回答