mhoang has asked for the wisdom of the Perl Monks concerning the following question:

Hello guys, I have two text files: file1.txt

"A123","valueA1","valueB1" "B234","valueA2","valueB2" "C345","valueA3","valueB3" "D456","valueA4","valueB4" "E567","valueA5","valueB5" "F678","valueA6","valueB6"
file2.txt
"C345","valueX1","valueY1" "D456","valueX2","valueY2"
I want to replace the value in file 1 with the second column value in file 2 if the key is matched.
"A123","valueA1","valueB1" "B234","valueA2","valueB2" "C345","valueX1","valueB3" "D456","valueX2","valueB4" "E567","valueA5","valueB5" "F678","valueA6","valueB6"
and here is my code, but I actually don't know how to write back to file1 with new value. Pls shed some light into it thanks.

#!/usr/bin/perl #use strict; #use warnings; open fh1,"<C:/Perl-Script/file1.txt"; open fh2,"<C:/Perl-Script/file2.txt"; open fh3,">>C:/Perl-Script/file3.txt"; @a=<fh1>; @b=<fh2>; foreach $b(@b) { @k = split ' ', $b; $hash2{$k[0]} = $k[1]; } foreach $a(@a) { @k = split ' ', $a; $hash1{$k[0]} = $k[1]; } while(($k,$v)= each %hash1) {$hash1{$k} = $hash2{$k} if (exists $hash2{$k})}; foreach $value (@a) { print fh1 $value; }

Replies are listed 'Best First'.
Re: Replace value in the text file
by huck (Prior) on Jun 28, 2017 at 05:54 UTC

    Leaving aside the issue of better ways to parse a CSV file, and single letter var names. But fixing use strict/warnings via my, and fixing bareword filehandles and 2 arg opens, and fixing that changing %hash1 did nothing to what was in @a

    #!/usr/bin/perl use strict; use warnings; open my $fh2,"<","file2.txt"; my %hash2; while (my $line=<$fh2>){ chomp $line; my @k = split ',', $line; $hash2{$k[0]} = $k[1]; } close $fh2; open my $fh1,"<","file1.txt"; my @final; while (my $line=<$fh1>){ chomp $line; my @k = split ',', $line; $k[1] = $hash2{$k[0]} if (exists $hash2{$k[0]}); push @final,join(',',@k); } close $fh1; open my $fh3,">","file1.txt"; for my $value (@final) {print $fh3 $value."\n";} close $fh3;

      use autodie; for error checking, see autodie
Re: Replace value in the text file
by Marshall (Canon) on Jun 28, 2017 at 07:13 UTC
    I came up with similar to huck
    #!/usr/bin/perl use warnings; use strict; my $file1=<<END; "A123","valueA1","valueB1" "B234","valueA2","valueB2" "C345","valueA3","valueB3" "D456","valueA4","valueB4" "E567","valueA5","valueB5" "F678","valueA6","valueB6" END my $file2=<<END; "C345","valueX1","valueY1" "D456","valueX2","valueY2" END my %hash; # read file1 into a memory hash table open (FILE1, '<', \$file1) or die "$!"; while (my $line = <FILE1>) { chomp $line; my ($key,@vals) = split ',',$line; $hash{$key} = [@vals]; } # process file2, modify the memory hash table open (FILE2, '<', \$file2) or die "$!"; while (my $line = <FILE2>) { chomp $line; my ($key,$val1) = split ',',$line; $hash{$key}[0] = $val1 if $hash{$key}; } # dump the hash table foreach my $key (sort keys %hash) { print "$key,", join(",",@{$hash{$key}}),"\n"; } __END__ Prints: "A123","valueA1","valueB1" "B234","valueA2","valueB2" "C345","valueX1","valueB3" "D456","valueX2","valueB4" "E567","valueA5","valueB5" "F678","valueA6","valueB6"
Re: Replace value in the text file
by tybalt89 (Monsignor) on Jun 28, 2017 at 17:29 UTC
    #!/usr/bin/perl # http://perlmonks.org/?node_id=1193751 use strict; use warnings; use Path::Tiny; my %hash = map /^("\w+"),("\w+")/, path('file2.txt')->lines; my $pattern = do { local $" = '|'; qr/@{[ keys %hash ]}/ }; path('file1.txt')->edit_lines( sub { s/^($pattern).\K"\w+"/$hash{$1}/ +} );
Re: Replace value in the text file
by mhoang (Acolyte) on Jun 28, 2017 at 23:46 UTC

    Thank you very much for your fast respond. I understand Marshall and Huck solution, but not sure tybalt89 solution. Tyball89, can you explain in detail what you did, please?

      I understand Marshall and Huck solution, but not sure tybalt89 solution.

      Don't worry, tybalt89 has the nasty habbit of posting completely uncommented, unexplained code that may or may not work; sometimes it works only accidentally.

      Your best bet for handling CSV data is to use Text::CSV_XS, its slower pure-perl implementation Text::CSV, or DBI in combination with DBD::CSV. The latter pair uses Text::CSV_XS behind the scenes to provide an SQL interface to the data in CSV files.

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
        Text::CSV_XS, its slower pure-perl implementation Text::CSV

        From the doc of the latter:

        Text::CSV is a thin wrapper for Text::CSV_XS-compatible modules now. ... Text::CSV uses Text::CSV_XS by default, and when Text::CSV_XS is not available, falls back on Text::CSV_PP, which is bundled in the same distribution as this module.

        Personally, I usually recommend Text::CSV, although I guess I should start telling people to make sure Text::CSV_XS is installed as well :-)

      I am just a beginner so please be patient with me,thanks. Macy