【问题标题】:delete few lines below a pattern until a blank line is found using perl code删除模式下方的几行,直到使用 perl 代码找到空行
【发布时间】:2015-01-14 02:23:53
【问题描述】:

我有一个文件,我想在其中删除模式后的几行,直到在其下方找到一个空行,然后使用 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

谢谢

【问题讨论】:

  • 您要删除包含描述的整行,还是只删除描述?也许您期望输出的示例会很有用。
  • ok..我正在稍微修改一下我的文件内容,以便您理解。
  • 你能把预期的输出轻松解决问题吗?
  • 我认为您已经为您未提及或匹配相应输出的输入放置了 2 个不同的文件。你能再检查一次吗?
  • Okiee 我明白你的意思。我已经查看了你修改过的代码!!

标签: perl


【解决方案1】:

由于您所做的替换取决于之前的匹配,您可以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

【讨论】:

  • 你能解释一下下面这行吗:my $new_data = $old_file =~ s/(.HEADER.*?\n).*?(\n.HEADER.*?\n).*/${1}${description1}${2}${description2}/msr; say $new_data;
  • 当然,我在帖子上做这件事。
  • 你已经使用'HEADER'来做你的代码......但是如果我有NAMES而不是HEADER1MAIL_ADD而不是HEADER2......那么如何我可以吗?
  • 我已经修改了我的代码和我的问题。没有名为 set.sh 的文件。我错误地把它放在那里。我的输入输出文件是一样的...file.txt...
  • 不能像那样更改内存中的同一个文件,只需创建一个新文件,然后根据需要重命名或覆盖。
【解决方案2】:

在你给$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/)

【讨论】:

  • 感谢您提供的信息... :) 我会更正我的代码。但现在我仍然无法得到我的输出.. 你能帮我吗
【解决方案3】:

希望这会有所帮助..

#!/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";
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-07
    • 1970-01-01
    • 2012-03-09
    • 1970-01-01
    • 1970-01-01
    • 2016-07-13
    • 1970-01-01
    相关资源
    最近更新 更多