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

while going through input file with each line as below format with below script

--file--
server1 M.22 s.23 2 AB 192.16.1.1 0 42 BBS 50
server3 M.22 s.33 2 AB 192.16.1.2 0 42 BBS 50 MK
server3 M.49 s.49 3 BB 10.1.1.1 0 42 BS 50
and more............
Program runs fine but I am only trying to replace 10th field's 50 with something else and since data is random, sometimes field 3 has 50 or 150 on it and messing up the program.
Can someone please give me a pointer for me to write this better ?
I am guessing
if ($cou) { $orig =~ s/\b$itemY\b/$default/; print "$orig\n";
is just looking at whichever 50 that occurs first and doing the substituion.
Can someone please give me a pointer on this
while (<>) { chomp; my $orig = $_; if ($orig =~ /^#/) { print "$_\n"; next; } if ($orig =~ /^$/) { print "$_\n"; next; } if (/(\w+)\s+M\.\d+\s+(s\.\d+)\s+(\S+\s+){6}(\d+)(.+)?$/) { #server1 yahoo.22 s.50 2 ABCCD 192.168.1.1 0 42 BBS + 50 my $cou = 1; my $item = join('@', $2, $1); my $itemY = $4; for my $i_carriers (keys %s_carriers) { if ("$item" eq "$i_carriers") { my $itemX = $s_carriers{$item}; $orig =~ s/\b$itemY\b/$itemX/; print "$orig\n"; $cou = 0; } last if ! $cou; } if ($cou) { $orig =~ s/\b$itemY\b/$default/; print "$orig\n"; } } }

Replies are listed 'Best First'.
Re: regex question
by moritz (Cardinal) on Nov 12, 2007 at 08:50 UTC
    My suggestion is to split at the whitespace, and take or modify those parts you need. Afterwards you can join them again.

    For example:

    my @fields = split m/ /, $line; $fields[9] = 50; print join ' ', @fields;
Re: regex question
by narainhere (Monk) on Nov 12, 2007 at 10:34 UTC
    If you want to be precise on which field you are replacing, Anchoring(i.e Look-ahead and look-behind) would help. The following snippet illustrates how to replace the nth field.
    This would replace the 2nd field
    use strict; use warnings; my $str="1 2 3 4 5 6 7 8 9 10"; print "string is $str\n"; $str=~s/(?<=(\d\s){1})\d*/I am replaced/; print "string is $str";
    Whereas if you want to replace 1st field use
    $str=~s/(?<=(\d\s){0})\d*/I am replaced/;
    Guesses for 10 th field ??
    More info on look-ahead and look-behind here.

    The world is so big for any individual to conquer

      The problem with the approach you advocate here is that look-behind assertions are fixed width so you can't do something like (?<=\d+\s). If you declare the string like this

      my $str="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15";

      how do you replace the 12th field?

      I'm all for look-around assertions but I don't think they are suited to this particular problem.

      Cheers,

      JohnGG

        I thought of look behind but decide against it since field 9 can and will have dynamic variables..

        still working on this.
Re: regex question
by siva kumar (Pilgrim) on Nov 12, 2007 at 09:08 UTC
    Split and join should be the good solution.