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

Hi, I need a script to find and replace some stuff from a certain part of a text file (after, say, character 279) and then put the lines back together. i've done this, but I seem to belosing a column of text... there is one character missing in the new files that was in the old ones, but I can't figure out why (or where... though I would guess it's at 279, where by substring stiching goes on).

here is the code

#!/usr/bin/perl -w @infile = ('/mnt/ide0/home/wrml/ReturnA/KCRETA60.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA61.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA62.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA63.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA64.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA65.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA66.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA67.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA68.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA69.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA70.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA71.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA72.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA73.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA74.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA75.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA76.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA77.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA78.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA79.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA80.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA81.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA82.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA83.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA84.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA85.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA86.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA87.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA88.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA89.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA98.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA99.DAT', '/mnt/ide0/home/wrml/ReturnA/KCRETA00.DAT', '/mnt/ide0/home/wrml/ReturnA/KEN90.DAT', '/mnt/ide0/home/wrml/ReturnA/KEN91.DAT', '/mnt/ide0/home/wrml/ReturnA/KEN92.DAT', '/mnt/ide0/home/wrml/ReturnA/KEN93.DAT', '/mnt/ide0/home/wrml/ReturnA/KEN94.DAT', '/mnt/ide0/home/wrml/ReturnA/KEN95.DAT', '/mnt/ide0/home/wrml/ReturnA/KEN96.DAT', ); $outpath = '/mnt/ide0/home/wrml/FormatReturnA/'; use File::Basename 'basename'; %substitute = ( '0000I' => '00000', '0000J' => '-0001', '0000K' => '-0002', '0000L' => '-0003', '0000M' => '-0004', '0000N' => '-0005', '0000O' => '-0006', '0000P' => '-0007', '0000Q' => '-0008', '0000R' => '-0009', '0001I' => '-0010', '0001J' => '-0011', '0001K' => '-0012', '0001L' => '-0013' ); $alt = join '|', keys(%substitute); $regex = qr/($alt)/; open (COUNT, '>', '/mnt/ide0/home/wrml/ReturnA/Counter.txt'); foreach $file (@infile){ open(IN, '<', "$file") or warn $! and next; open(OUT, '>', $outpath.basename($file)) or warn $! and next; while (<IN>) { $Line = $_; $DataLine = substr($Line, 279); $DataLine =~ s/$regex/$substitute{$1}/g; $FirstLine = substr($Line, 0, 279); substr($FirstLine, -1, 1) = $DataLine; print OUT $FirstLine; $length = length($FirstLine); if ($length != 7383) { print COUNT "you have a problem in file $file. The lin +e is $length\n" } } }
I know I'm losing something because I ran a file to count the lines in each and the original is one character longer. that is, all the lines are 7387 long in the original and 1386 in the new... doing a simple 'length($TheLine)'. what have I done?

please help.

Janitored by Arunbear - replaced pre tags with code tags, to prevent distortion of site layout and allow code extraction.

Replies are listed 'Best First'.
Re: Lost Column
by Zaxo (Archbishop) on Aug 18, 2005 at 19:13 UTC

    You can act directly on the substring within the line like this:

    while (<IN>) { substr($_,279) =~ s/$regex/$substitute{$1}/g; print OUT $_; }

    I don't see exactly what's truncating your lines, but that simplification may help spot it.

    After Compline,
    Zaxo

Re: Lost Column
by japhy (Canon) on Aug 18, 2005 at 19:19 UTC
    This is line is causing it: substr($FirstLine, -1, 1) = $DataLine. As someone already mentioned, you should really just use the regex on the returned value from substr() (Perl is magic like that). Or, you could do $FirstLine .= $DataLine to append one string to the end of another.

    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
      thanks for your help. I see why this is a better code, but now when I do what Zaxo has suggezted, I get a failure saying:
      substr outside of string at /mnt/ide0/home/wrml/ReturnA/ReturnAReplace +r.pl line 88, <IN> line 8453
      This did not happen before. how can this be happening now? What does it mean that the substring is outside of the string?
        Sounds like the offset is beyond the end of the string being substringed. For example:
        my $woopsie = substr("Short line.",100);
        causes the same error message. Could you show us your revised code?