删除模式下面的几行,直到使用perl代码找到一个空行

时间:2014-11-17 08:13:24

标签: perl

我有一个文件,其中我想删除一个模式之后的几行,直到在它下面找到一个空行,然后在使用perl的模式之后添加一个新行。 这是输入文件:

[NAMES]
Mark
Shaun

[MAIL_ADD]
douglas@mail.com
iamshaun@mail.com
mbirenk@mail.com

我想删除每个标题的描述部分并在其中添加新描述。我的perl代码如下所示,它只在每个标题下面添加新的描述。我无法删除旧说明:

#!/usr/bin/perl -w
use warnings;
open(my $var, "<file.txt");
my @arr = <$var>;
my $cnt =0;
my $description1 = "Biren\nKumar\nStephen"
my $description2 = "rahul123@mail.com\nshael@mail.com"
while($cnt < @arr)
{
  my $cur_line = $arr[$cnt];
  if ($cur_line =~ s/\[NAMES\]/\[NAMES\]\n$description1/)
  {
    $arr[$cnt] = $cur_line;
  }
  elsif ($cur_line =~ s/\[MAIL_ADD\]/\[MAIL_ADD\]\n$description2/)
  {
    $arr[$cnt] = $cur_line;
  }
  $cnt++;
}
close($var);
open(my $var1, ">file.txt");
my $cnt1 =0;
while($cnt1 < @arr)
{
  print $var1 $arr[$cnt1];
  $cnt1++;
}
close $var1;

请帮助我..如果你无法理解我的问题那么请告诉我,我会尝试澄清更多。

我的输出文件应如下所示:

[NAMES]
Biren
Kumar
Stephen

[MAIL_ADD]
rahul123@mail.com
shael@mail.com

由于

3 个答案:

答案 0 :(得分:0)

由于您所做的替换取决于之前的匹配,您可以slurp该文件,只需更改HEADER1和HEADER2之间的内容:

use strict;
use warnings;
use v5.18;
my $old_file = do { local $/; <DATA> };
my $description1 = "Biren\nKumar\nStephen";
my $description2 = "rahul123\@mail.com\nshael\@mail.com";
my $new_data = $old_file =~
    s/(.HEADER.*?\n).*?(\n.HEADER.*?\n).*/${1}${description1}${2}${description2}/msr;
say $new_data;

__DATA__
[HEADER1]
Mark
Shaun

[HEADER2]
douglas@mail.com
iamshaun@mail.com
mbirenk@mail.com

这是输出:

[HEADER1]
Biren
Kumar
Stephen
[HEADER2]
rahul123@mail.com
shael@mail.com

如果您需要保留旧值,我也会使用non-destructive substitution

如果您需要,可以使用以下文件:

use strict;
use warnings;
use v5.18;
open(my $var, "<file.txt"); #open file to read
my $old_file = do { local $/; <$var> };
my $description1 = "Biren\nKumar\nStephen";
my $description2 = "rahul123\@mail.com\nshael\@mail.com";
my $new_data = $old_file =~
    s/(.HEADER.*?\n).*?(\n.HEADER.*?\n).*/${1}${description1}${2}${description2}/msr;
close $var;
open(my $var1, ">file.txt"); #open file to write
say $var1 $new_data;

正则表达式行正在执行以下操作:

  • (.HEADER。*?\ n)将第一个HEADER行中的所有内容存入$ 1
  • 。*?匹配第一个标题行下的所有内容(我们不会存储或使用它)
  • (\ n.HEADER。*?\ n)将第二个HEADER行中的所有内容存入$ 2
  • $ {1} $ {description1} $ {2} $ {description2}用所需的输出替换您的输入
  • / msr多行,单行可以匹配\ n和非破坏性替换

Link for docs on modifiers

答案 1 :(得分:0)

$description2

的作业中
my $description2 = "rahul123@mail.com\nshael@mail.com";

你有@是内插的。由于您尚未定义名为@mail的数组,@mail的内插会导致空字符串,因此$description2

"rahul123.com\nshael.com

此外,在您的替换行中,您使用表示字符类的特殊字符[]。你应该逃避他们:

elsif ($cur_line =~ s/\[HEADER2\]/\[HEADER2\]\n$description2/) 

而不是

elsif ($cur_line =~ s/[HEADER2]/[HEADER2]\n$description2/)

答案 2 :(得分:0)

希望这会有所帮助..

#!/usr/bin/env perl
use strict;
use warnings;

push @ARGV, 'file.txt';

my %dump;
my $header;

while (<>) {
  if (/^\[([^\]]+)\]$/) {
    $header = $1;
    $dump{$header} = "";
    next;
  }
  $dump{$header} .= $_ if $header;
}

# ==== here do the change ===
$dump{"NAMES"} = <<EOL;
Biren
Kumar
Stephen
EOL

$dump{"MAIL_ADD"} = <<EOL;
rahul123@mail.com
shael@mail.com
EOL
# ===========================

# now print it back to <STDOUT>
foreach (sort keys %dump) {
  chomp($dump{$_});
  print "[$_]\n$dump{$_}\n\n";
}