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

Hi, I am still learning Perl. I am trying to do the following search an replace for a txt file. But have no clue how to do this. Any help and code example is appreciated. Thanks. Sample Data:
57KXNWLRZWJ3 057E8bf0D030 057E8bf0D032 58KXNWLRZWKB 058E8bf0D02A 058E8bf0D02C
Problem: 1. Generate a 2 digit random number. Replace the first two digits in row 1 (e.g 57) with the new number. Use the same generated number for next two rows. Repeat the process for next 3 rows and so on, till EOF. 2. generate random number to replace the last two digits in row 2 & 3 then repeat the process for 5 & 6 and so on, till EOF. The result file will look like this. Let's say we generated a random number 12 and then next random number is 22. Also last two digits were replaced with the randomly generated numbers.
12KXNWLRZWJ3 012E8bf0D011 012E8bf0D067 22KXNWLRZWKB 022E8bf0D020 022E8bf0D023

Replies are listed 'Best First'.
Re: Search and replace text
by swampyankee (Parson) on Jan 26, 2006 at 23:20 UTC

    This reeks of being a homework assignment, so my assistance will be limited to two items:

    1: To generate a 2 digit random number, you could use something like:

    $x = int(rand(100));
    You'll need the number, so hang onto it.

    2: Read the Perl documentation. You could do something like this:

    $y =~ s!^\d{2}!$x!;
    where $x is your random value and $y the line you're changing.

    The actual i/o and program logic will be left as an exercise.

    emc

    " When in doubt, use brute force." — Ken Thompson
Re: Search and replace text
by BrowserUk (Patriarch) on Jan 26, 2006 at 23:20 UTC

    This assumes that your sample data is a true reflection of it. Ie. Fixed length records of 12 chars + newline.

    Update: Removed redundant regex.

    #! perl -sw use strict; $/ = \39; ## Read 3 lines as a single record while( <DATA> ) { my $rep = sprintf '%02d', int rand 100; substr $_, 0, 2, $rep; substr $_, 14, 2, $rep; substr $_, 27, 2, $rep; print; } __DATA__ 57KXNWLRZWJ3 057E8bf0D030 057E8bf0D032 58KXNWLRZWKB 058E8bf0D02A 058E8bf0D02C

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      You're missing
      substr $_, 23, 2, sprintf '%02d', rand 100; substr $_, 36, 2, sprintf '%02d', rand 100;
      and your int is useless.

        I kinda assumed that once the OP had seen the idea of reading the data as fixed length records, he could probably work the rest out for himself.

        As for the int being useless here, point taken. but it's a good habit I think to explicitly truncate the return from rand if you are trying to generate an integer result. In this case it will be autotruncated, but in other situations it will not.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Search and replace text
by ikegami (Patriarch) on Jan 26, 2006 at 23:21 UTC

    Like this?

    my $num; while (<FILE>) { chomp; if ($. % 3 == 1) { $num = sprintf("%02d", rand(100)); substr($_, 0, 2, $num); } else { substr($_, 1, 2, $num); substr($_, -2, 2, sprintf("%02d", rand(100))); } print("$_\n"); }

    If the line terminator is one character long, the above is simplifies to:

    my $num; while (<FILE>) { if ($. % 3 == 1) { $num = sprintf("%02d", rand(100)); substr($_, 0, 2, $num); } else { substr($_, 1, 2, $num); substr($_, -3, 2, sprintf("%02d", rand(100))); } print; }
      Thanks everyone. I have another related question. Is it possible to randomly generate char within a certain range? For example if i want to generate two random chars between "aa" and "ff" so that the output will be like
      ab ad df ca . . .
      PS. this is not a homework assignment. I finished college long ago. I just learn new tools to help me do my job and Perl is the mother of all tools.
Re: Search and replace text
by nsyed (Novice) on Jan 27, 2006 at 04:02 UTC
    Thanks everyone. I have another related question. Is it possible to randomly generate char within a certain range? For example if i want to generate two random chars between "aa" and "ff" so that the output will be like
    ab ad df ca . . .
    PS. this is not a homework assignment. I finished college long ago. I just learn new tools to help me do my job and Perl is the mother of all tools.

      Here are a couple of ways:

      print join'',map{ chr 97+rand(6) } 1 .. 2 for 1 .. 100; ## Slightly wasteful, but you only do it once ## and reuse the array each time. my @pairs = grep{ /[a-f]{2}/ }'aa' .. 'ff'; print $pairs[ rand @pairs ];

      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.