Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Compare two file text input, compare it, replace and write new file

by wa2nlinux (Novice)
on Feb 14, 2012 at 05:00 UTC ( [id://953613]=perlquestion: print w/replies, xml ) Need Help??

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

Hello all, I got problems in perl. I have 2 text file call it 1) data 2) source.txt The data file contain teks file like this :
\tl:&#xa12 \tr:&#xa13 \ca:&#xa15 \ra:&#xa16 \ka:&#xa17 ...
Data file contain two colomn "key" and "values" separated by ":" and the source.txt contain
\tl\ca\ra\tr\ka ...
source.txt file contain "key" such as in data file. I need a new file call it target.txt that contain "values" form data according to "keys" in source.txt
&#xa12&#xa15&#xa16&#xa13&#xa17
#!/usr/bin/perl use strict; use warnings; my $dfile = 'data'; my $sfile = 'source.txt'; my $tfile = 'target.txt'; open (DFILE,$dfile) or die "can not open"; open (SFILE,$sfile) or die "can not open"; open (TFILE,"> $tfile") or die "can not open"; my %words; while (<DFILE>) { chomp; my ($key, $val) = split /:/; $words{$key} .= exists $words{$key} ? "$val" : $val; }; while (my $s = <SFILE>) { chomp($s); my @words = split / /, $s; foreach my $val (@words) { } for my $i (0 .. $#words) { $words[$i] = $words{$words[$i]} if (exists($words{$words[$i]})) } print TFILE join(' ', @words),$/; print TFILE "<br>"; } close(SFILE); close(DFILE); close(TFILE);
The code above work if only if the source.txt contain keys separated with space,
\ca \ra \ka \tl
but fail to work if source.txt is
\ca\ra\ka\tl
I try to make hash from data but I confuse how to compare it and replace it, if source.txt contain "keys" without space

Replies are listed 'Best First'.
Re: Compare two file text input, compare it, replace and write new file
by kcott (Archbishop) on Feb 14, 2012 at 05:23 UTC

    To populate your hash, change

    $words{$key} .= exists $words{$key} ? "$val" : $val;

    to

    $words{$key} = $val;

    -- Ken

Re: Compare two file text input, compare it, replace and write new file
by repellent (Priest) on Feb 14, 2012 at 06:29 UTC
    You are splitting your source.txt lines with a single whitespace:
    my @words = split / /, $s;

    For your code to work, source lines have to look like keys separated by single whitespaces.

    Hmm.. it seems like split may not be the right tool, since it's hard to specify what to really split on. Try regex search and replace!
    # match a backslash followed by two characters, # then compute the replacement by looking into %words $s =~ s{(\\..)}{ $words{$1} || $1 }ge;

    Have a look at perlrequick and perlretut. (And follow kcott's advice.)
      the text is already formated, such as
      \ha\hang\hu\hung
      can I using search replace if the format like in the code above ? because the codes sometime having same first or second characters such as \ha and  \hang My code already work but if I manually add a space after the code  \ha\ca\ra\ka to \ha \ca \ra \ka
Re: Compare two file text input, compare it, replace and write new file
by jwkrahn (Abbot) on Feb 14, 2012 at 07:28 UTC
    open (DFILE,$dfile) or die "can not open"; open (SFILE,$sfile) or die "can not open"; open (TFILE,"> $tfile") or die "can not open";

    That would be better as:

    open DFILE, '<', $dfile or die "can not open '$dfile' because: $!"; open SFILE, '<', $sfile or die "can not open '$sfile' because: $!"; open TFILE, '>', $tfile or die "can not open '$tfile' because: $!";


    $words{$key} .= exists $words{$key} ? "$val" : $val;

    That would be better as:

    $words{$key} .= $val;


    while (my $s = <SFILE>) { chomp($s); my @words = split / /, $s;

    That would be better as:

    while ( <SFILE> ) { my @words = split;


    for my $i (0 .. $#words) { $words[$i] = $words{$words[$i]} if (exists($words{$words[$i]})) }

    That would be better as:

    for my $word ( @words ) { $word = $words{ $word } if exists $words{ $word }; }


    print TFILE join(' ', @words),$/; print TFILE "<br>";

    That would be better as:

    print TFILE "@words\n<br>";


    The code above work if only if the source.txt contain keys separated with space,

    \ca \ra \ka \tl

    but fail to work if source.txt is

    \ca\ra\ka\tl
    $ perl -le'$_ = q/\ca\ra\ka\tl/; print; print for split /(?=\\)/' \ca\ra\ka\tl \ca \ra \ka \tl
      OK the newest code :
      #!/usr/bin/perl use strict; use warnings; my $dfile = 'data'; my $sfile = 'source.txt'; my $tfile = 'target.html'; open DFILE, '<', $dfile or die "can not open '$dfile' because: $!"; open SFILE, '<', $sfile or die "can not open '$sfile' because: $!"; open TFILE, '>', $tfile or die "can not open '$tfile' because: $!"; my %words; while (<DFILE>) { chomp; my ($key, $val) = split /:/; $words{$key} = $val; }; while ( <SFILE> ) { my @words = split /(?=\\)/; for my $word ( @words ) { $word = $words{ $word } if exists $words{ $word }; } print TFILE "@words\n<br>"; } close(SFILE); close(DFILE); close(TFILE);
      having source.txt :
      \ca\ra\ka\tl \ca\ra\ka\tl
      the last character of line (\tl) not replace by value on data. The result in target.html is :
      &#xa15 &#xa16 &#xa17 \tl <br>&#xa15 &#xa916 &#xa17 \tl
        Solved by adding chomp
        while ( <SFILE> ) { chomp my @words = split /(?=\\)/; for my $word ( @words ) { $word = $words{ $word } if exists $words{ $word }; } print TFILE "@words\n<br>"; }
        another question: is it OK, if I used hash array my "data" (DFILE) on that program contain about 5000 lines ?
        my %words; while (<DFILE>) { chomp; my ($key, $val) = split /:/; $words{$key} = $val; };

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://953613]
Approved by kcott
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (8)
As of 2024-04-18 06:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found