perl-用哈希替换字段值

perl-用哈希替换字段值,perl,Perl,我需要根据第2列的值替换txt文件列中的值 我有示例_data.txt文件: Name Group Value ID1 1 1.00 ID2 1 2.00 ID3 1 3.00 ID4 1 4.00 ID5 2 5.00 ID6 2 6.00 ...................... ID10 10 7.00 和示例_values.csv文件,以逗号分隔: 1,6.

我需要根据第2列的值替换txt文件列中的值

我有示例_data.txt文件:

Name   Group Value
 ID1    1      1.00
 ID2    1      2.00
 ID3    1      3.00
 ID4    1      4.00
 ID5    2      5.00
 ID6    2      6.00
......................
ID10   10      7.00
和示例_values.csv文件,以逗号分隔:

1,6.00
2,7.00
......
10,15.00
替换的文件应如下所示:

Name   Group Value
 ID1    1      6.00
 ID2    1      6.00
 ID3    1      6.00
 ID4    1      6.00
 ID5    2      7.00
 ID6    2      7.00
......................
ID10   10     15.00
保持字段之间的格式和空格数很重要

到目前为止,我已经得出了以下结论:

#!/usr/bin/perl

use strict;
use warnings;


open(VAL, "<", "example_values.csv") or die $!;
my %hash;
%hash = ( %hash, (split(/,/, $_))) while ( <VAL> );


my $file = '<example_data.txt';
open my $info, $file or die "Could not open $file: $!";
open OUT, ">values_replaced.txt";
my @F = ();
my $k = ();
my %F = ();

while( my $line = <$info>)  {
    if ($line =~ /ID/) {   
        my @fields = split " ";
        s/$F[1]/%hash($k){$F[0]}/; 
        print OUT $line; 
    } else {
        print OUT $line;
    }
}

close(OUT) || die "Couldn't close OUT properly";
#/usr/bin/perl
严格使用;
使用警告;
打开(VAL,“values_replaced.txt”;
我的@F=();
我的$k=();
我的%F=();
while(我的$line=){
如果($line=~/ID/){
我的@fields=split”“;
s/$F[1]/%hash($k){$F[0]}/;
打印$line;
}否则{
打印$line;
}
}
关闭(关闭)| |模具“无法正确关闭”;
我收到的错误消息是:

Use of uninitialized value $F[1] in regexp compilation at perl.pl line 22, <$info> line 18.
Use of uninitialized value $_ in substitution (s///) at perl.pl line 22, <$info> line 18.
在perl.pl第22行、第18行的regexp编译中使用未初始化值$F[1]。
在perl.pl第22行、第18行的替换(s//)中使用未初始化的值$。
但输出文件是编写的,它只是输入文件的副本


非常感谢您的帮助,我对perl还不太熟悉,现在真的被卡住了。

看起来这是家庭作业。我将提供一个有效的解决方案和解释,但我希望我不必提醒您,您应该自己解决这个问题,而不是让其他人帮您解决

  • 很好,您有
    使用严格的
    使用警告
    :)

  • 您正在混合词法文件句柄(
    $fh
    )和旧式全局文件句柄(
    OUT
    )。只需使用词法,就像
    打开我的$fh,“看起来这是家庭作业。我将提供一个有效的解决方案和解释,但我希望我不必提醒您,您应该尝试自己解决这个问题,而不是让其他人为您解决

    • 很好,您有
      使用严格的
      使用警告
      :)

    • 您正在混合词法文件句柄(
      $fh
      )和旧式全局文件句柄(
      OUT
      )。只需使用词法,像打开我的$fh一样,初始化
      @F=(),则决不向阵列分配/推送任何其他内容。您希望在
      $F[1]
      中找到什么价值?您希望它是如何实现的?您显然使用了大量不同的源代码。这里有几个问题。
      $k
      应该做什么?类表文件选项卡是否被分隔?您应该在类
      VAL
      的纯文字文件句柄和类
      $info
      的词法文件句柄之间进行选择,并坚持使用。不要把它们混在一起。(你的选择应该是词法句柄。)你初始化
      @F=(),则决不向阵列分配/推送任何其他内容。您希望在
      $F[1]
      中找到什么价值?您希望它是如何实现的?您显然使用了大量不同的源代码。这里有几个问题。
      $k
      应该做什么?类表文件选项卡是否被分隔?您应该在类
      VAL
      的纯文字文件句柄和类
      $info
      的词法文件句柄之间进行选择,并坚持使用。不要把它们混在一起。(你的选择应该是词法句柄。)“你用来从VAL读取的构造很好”我不会说得那么好。我能提供
      split/\s+/;如果…
      可替换为
      拆分,则移位-它默认为
      '
      作为分隔符,跳过前导空格。@sob继续。我在打电话。改变它:-)@Borodin我改变了那个短语。你说得对,我不清楚。谢谢你。@Sobrique谢谢你修改它。下次再更新评论时,它不适合您的编辑;-)“你用来阅读VAL的结构很好”我不会说得那么好。我能提供
      split/\s+/;如果…
      可替换为
      拆分,则移位-它默认为
      '
      作为分隔符,跳过前导空格。@sob继续。我在打电话。改变它:-)@Borodin我改变了那个短语。你说得对,我不清楚。谢谢你。@Sobrique谢谢你修改它。下次再更新评论时,它不适合您的编辑;-)
      use strict;
      use warnings;
      use autodie;    # always die when open fails
      
      # Slurp the mapping. This works on $_ and returns a list
      # that ends up in the hash.
      open my $fh_values, "<", "scratch/example_values.txt";
      my %group_value_map = map { chomp; split /,/; } (<$fh_values>);
      close $fh_values;
      
      open my $fh_out, '>', '...';
      
      my $file = 'scratch/example_data.txt';
      open my $fh_in, '<', $file;
      
      while ( my $line = <$fh_in> ) {
          if ( $line =~ /ID/ ) {
              # split in " " discards preceeding whitespace and splits
              # on arbitrary long whitespace sequences (but only if you
              # use it on the right variable)
              my @fields = split " ", $line;
      
              # This replacement works nicely now, but will break horribly
              # in case an additional column is added :)
              $line =~ s/$fields[2]/$group_value_map{$fields[1]}/;
          }
      
          # since we modified $line we don't need an else block that prints the
          # same value as the last line of the then block
          print $line;
      }
      
      close $fh_in;
      close $fh_out;
      
      Name   Group Value
       ID1    1      6.00
       ID2    1      6.00
       ID3    1      6.00
       ID4    1      6.00
       ID5    2      7.00
       ID6    2      7.00
      ID10   10      15.00