我需要替换 Subjects ex :- Subjects :***** 但它给出了输出 :- Subjects :***** Computer

I need to replace Subjects ex :- Subjects :***** but it is giving the output :- Subjects :*****Computer

在这里您可以看到我的代码正在用 ***** 替换主题 但正在发生的事情是它没有取代第二行。 我一直在尝试这样做,但每次都失败了。如果有人可以帮助我,请查看

我想要的输出是:

Name : Piyush Prasad
Class : 12th
Stream : Science
Subjects :*****
Text : what ever happens to this code does not even matter to me 
Time :*****

我得到的输出是:

Name : Piyush Prasad
Class : 12th
Stream : Science
Subjects :*****Computer
Text : what ever happens to this code does not even matter to me 
Time :***** 

代码如下:

 my $fm_log= "
 -------------------------------------------------------------------------------
 Name : Piyush Prasad
 Class : 12th
 Stream : Science
 Subjects : Physics Chemistry Maths
            Computer
 Text : what ever happens to this code does not 
        even matter to me 
 Time : 10.304534
 ";
 my %fm_info;
 $fm_log =~ s!.*?(---------------)!!s;
 $fm_log =~ s!vwmg.*!!sg;
 my @fm_log = split(/-------+/, $fm_log);
 @fm_log = grep {! m!^\s*$!s} @fm_log;
 for (my $i = 0; $i < @fm_log;$i++){
     my $type = undef;
     my @tmp1 = split(/\R+/,$fm_log[$i]);
     foreach (@tmp1)
       {
         $_ =~ s!^\s+!xxxx! if $_ !~ m!:!;
         $_ =~ s!(Time\s+:)\s+.*!xxx!;
         $_ =~ s!(Subjects\s+:)\s+.*!xxx!;
       }
      $fm_log[$i] = join("\n",@tmp1);
      $fm_log[$i] =~ s!\R+xxxx!!mg;
       }
      print @fm_log;

你得到的原因

Subjects :*****Computer

而不是

Subjects :*****

是在换行符处拆分原始字符串 \R+,然后编辑这些行,然后将字符串重新连接在一起。由于 Computer 换行,因此不会被编辑。

 my @tmp1 = split(/\R+/,$fm_log[$i]);         # <---- splitting the line
 foreach (@tmp1) {                            # editing the pieces
     $_ =~ s!^\s+!xxxx! if $_ !~ m!:!;
     $_ =~ s!(Time\s+:)\s+.*!xxx!;
     $_ =~ s!(Subjects\s+:)\s+.*!xxx!;
 }
 $fm_log[$i] = join("\n",@tmp1);              # joining the pieces

换句话说,如果您有一个字符串,例如:

my $str = "foo: bar\nbaz"; 

然后在换行处拆分字符串并尝试删除 foo:

之后的所有内容
my @pieces = split /\R+/, $str;

现在 @pieces 将包含以下内容:

$VAR1 = [
      'foo: bar',
      'baz'
    ];

如果我们尝试用 s/foo:.*// 编辑它们,我们将永远不会影响原始字符串的 baz 部分。

由于您的文件包含由以单词开头、后跟冒号的行分隔的字段,然后是可能包含换行符的内容,因此您需要首先将字段彼此分开。

您的字段看起来像...

TITLE : CONTENT
        CONTENT ...
TITLE : CONTENT ...

可能有读取这种格式的模块更适合。我编写了这个快速 hack 来将数据强制转换为散列,您可以在其中通过简单地为字段分配新值来编辑字段。

use strict;
use warnings;
use Data::Dumper;

my $fm_log= " Name : Piyush Prasad
 Class : 12th
 Stream : Science
 Subjects : Physics Chemistry Maths
            Computer
 Text : what ever happens to this code does not 
        even matter to me 
 Time : 10.304534
 ";

my @info = split /^ *([\w ]+) : /m, $fm_log;   # split into fields
s/\s+/ /g for @info;                           # cleanup start
s/^\s+|\s+$// for @info;
shift @info;                                   # cleanup complete
my %info = @info;
print Dumper \%info;                 # show the data structure we made

$info{Subjects} = "****";
$info{Time} = "****";

printf("%s : %s\n", $_, $info{$_}) for qw(Name Class Stream Subjects Text Time);

这将输出

$VAR1 = {
          'Class' => '12th',
          'Stream' => 'Science',
          'Time' => '10.304534',
          'Subjects' => 'Physics Chemistry Maths Computer',
          'Text' => 'what ever happens to this code does not even matter to me',
          'Name' => 'Piyush Prasad'
        };
Name : Piyush Prasad
Class : 12th
Stream : Science
Subjects : ****
Text : what ever happens to this code does not even matter to me
Time : ****