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

I'm trying to parse a string that looks like this (Fortran namelist input):

WB(1,2)=    0.000, 1.23, TB(1,2)=     0.0,  253.0, TMB(1,2)=  0.0,  1.0,  SL(1,2)= 0.00, 1.00

I'd like to read the second number after WB(1,2)= (1.23 in the above example) and change it.

Is there a way to do this with regular expressions?

Thanks,
Matt

Replies are listed 'Best First'.
Re: parsing a line of text with inconsistent delimiters
by moritz (Cardinal) on Sep 12, 2007 at 14:59 UTC

      Does Fortran::Format do namelist i/o? I see no references to it in its documentation. Fortran::Namelist or Fortran::F90Namelist may be more appropriate. I've not used either, even though, as a long-time Fortran programmer, I find namelist i/o extremely handy.


      emc

      Information about American English usage here and here.

      Any New York City or Connecticut area jobs? I'm currently unemployed.

        Thanks Swampy. Fortran::Namelist looks like it will do the trick.
Re: parsing a line of text with inconsistent delimiters
by erroneousBollock (Curate) on Sep 12, 2007 at 15:05 UTC
    A regexp something like the following should match each such "second number" in the line.
    / [A-Z]+ # WB \(\d+,\d+\) # (1,2) \s*=\s* # = (?: # start non-capturing group \d+\.\d+, # a float followed by comma \s*(\d+\.\d+),? # capture a float (followed by comma?) ) # end-group /gx

    To change it use the substitution operator (perhaps with /e flag so that you can pass the matched number to a function to get back the value you want it to be changed to).

    -David

    Update: fixed a typo.
    Update2: and another, thanks naikonta.

      Oops,
      Unmatched ) in regex; marked by <-- HERE in m/ [A-Z]+ # WB \(\d+,\d+) <-- HERE # (1,2) \s*=\s* # = (?: # start non-capturing group \d+\.\d+, # a float followed by comma \s*(\d+\.\d+),? # capture a float (followed by comma?) ) # end-group / at /tmp/wb line 10.
      Matt, you can do it also with split but you have to join the parts back together after changing the part you want.
      $_ = 'WB(1,2)= 0.000, 1.23, TB(1,2)= 0.0, 253.0, TMB(1,2)= 0. +0, 1.0, SL(1,2)= 0.00, 1.00'; my @parts = split /, /; $parts[1] = 3.21; # change 1.23 with 3.21 $_ = join ', ', @parts; print $_, "\n"; # output: # WB(1,2)= 0.000, 3.21, TB(1,2)= 0.0, 253.0, TMB(1,2)= 0.0, +1.0, SL(1,2)= 0.00, 1.00

      Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!

Re: parsing a line of text with inconsistent delimiters
by mayaTheCat (Scribe) on Sep 12, 2007 at 15:11 UTC
    You can both extract the number and replace with the new ones, as given in the following snippet;
    # assuming; ... my $str = "WB(1,2)= 0.000, 1.23, TB(1,2)= 0.0, 253.0, TMB(1,2) += 0.0, 1.0, SL(1,2)= 0.00, 1.00"; sub replace { my ($extracted_number) = @_; # calculate or query the new number. For example; my $new_number = $extracted_number + 1; return $new_number; } $str =~ s/ (?<=,) # Precondition: There should be a comma before, \s* (\d+\.\d+) # ... and it should be a floating number! /replace($1)/xges; print "$str\n";

    ---------------------------------
    life is ... $mutation = sub { $_[0] =~ s/(.)/rand()<0.1?1-$1:$1/ge };

      Thank you to everyone who responded.