Loading ...
Sorry, an error occurred while loading the content.

Re: [PBML] Re: Pattern matching in an array

Expand Messages
  • Don Smith
    Charles, Thanks once again! I enjoy learning new things and I work with Perl as a hobby because its challenging. I look forward to the day when I feel
    Message 1 of 1 , Jul 2, 2002
    • 0 Attachment
      Charles,

      Thanks once again!

      I enjoy learning new things and I work with Perl as a 'hobby' because its
      challenging. I look forward to the day when I feel competent working with
      it, but until then, I'll just have fun and keep asking questions!

      Your guidance is very much appreciated.

      Don


      ----- Original Message -----
      From: "Charles K. Clarkson" <cclarkson@...>
      To: <perl-beginner@yahoogroups.com>
      Sent: Monday, July 01, 2002 11:14 AM
      Subject: [PBML] Re: Pattern matching in an array


      "Don Smith" <dmsmith@...> recently wrote:

      : Thanks for your reply to my question yesterday. In response to
      : your questions and your suggestion I post the code that wasn't
      : working, I did two things... First I went to bed and got some
      : sleep, and then I got up today (I can't say this morning!) and
      : actually got my code working. As I wrote it step by step,
      : figuring things out and commenting them in the script as I
      : went along, I came to the conclusion that this might be helpful
      : to fellow beginners.

      There are some mistakes in the code that I would like to point
      out to you. We can all learn from it. I'll do the

      : I don't pretend its a 'good' script or that my style is proper, but
      : it does what I want, it helped me learn a bit about arrays and
      : pattern matching and it was fun seeing it work!

      Congratulations!

      There's more to learn and I'd like to point out some ideas
      dealing with subroutines to you.

      : The reason I want to 'clean' data going into the database is
      : because it happens quickly during submission and I don't have
      : to worry about it again. If I had a large database and had to
      : clean the characters before displaying the data, it
      : could take awhile, depending on the size of the database.

      True. As long as your customer is okay with not having the
      raw data. And you take the changed data into account when
      doing searches.

      : I'd appreciate your comments on how it could be improved.

      Okay, but remember, you asked for it.

      Let's start with the subroutine. I've stripped the comments
      and some white space:

      sub char_to_html {
      my ($count, $list);
      $count = 0;
      while ($list[$count] ne "") {
      $list[$count] =~ s/\&/\&\#38;/g;
      $list[$count] =~ s/\$/\&\#36;/g;
      $list[$count] =~ s/\"/\&\#34;/g;
      $list[$count] =~ s/\%/\&\#37;/g;
      $list[$count] =~ s/\(/\&\#40;/g;
      $list[$count] =~ s/\)/\&\#41;/g;
      $list[$count] =~ s/\*/\&\#42;/g;
      $list[$count] =~ s/\//\&\#47;/g;
      $list[$count] =~ s/\:/\&\#58;/g;
      $list[$count] =~ s/\?/\&\#63;/g;
      $list[$count] =~ s/\[/\&\#91;/g;
      $list[$count] =~ s/\\/\&\#92;/g;
      $list[$count] =~ s/\]/\&\#93;/g;
      $list[$count] =~ s/\^/\&\#94;/g;
      $list[$count] =~ s/\{/\&\#123;/g;
      $list[$count] =~ s/\|/\&\#124;/g;
      $list[$count] =~ s/\}/\&\#125;/g;
      $list[$count] =~ s/\~/\&\#126;/g;
      $list[$count] =~ s/\</\&\#139;/g;
      $list[$count] =~ s/\>/\&\#155;/g;
      # $list[$count] =~ s/\@/\&\#64;/g;
      $count++;
      }
      }

      A few items:
      - You shouldn't need a counter for 1 array.
      - You shouldn't need to do so many passes on each element.
      - @list was never passed to the subroutine.
      - < and > 'ord' to 60 and 62, not 139 and 155.

      A good subroutine should be written to stand on its own.
      It shouldn't be manipulating the data outside its own block.
      (Except in rare circumstances.)

      So first let's look at how char_to_html() was called.
      Here is the call:

      &char_to_html;

      Re-read perlsub. Calling a sub with the & rarely does what
      people think it does. Since we need to work on @list, let's
      pass it and return it.

      @list = char_to_html( @list );

      Or:
      my @clean_list = char_to_html( @list );

      When we pass @list to char_to_html() we accomplish
      many things:
      - The code is self-documenting.
      - We know exactly what char_to_html() is working on.
      - We can guess that char_to_html() is returning a list or an array.

      It would actually be best to pass an array reference, but
      we'll stick with arrays and not introduce that concept here.


      First, let's look at the multiple passes. You pointed out
      reasons for doing the '&' substitution first, but the others
      could be combined. This should do it:

      s!([\$"%()*/:?[^\]{|}~<>\\])!sprintf '&#%d;', ord $1!ge;

      I won't go into how this works. This message is long
      enough. Read up on perlre.

      This reduces the sub to:

      sub char_to_html {
      my ($count, $list);
      $count = 0;
      while ($list[$count] ne "") {
      $list[$count] =~ s/\&/\&\#38;/g;
      $list[$count] =~ s!([\$"%()*/:?[^\]{|}~<>\\])!sprintf '&#%d;', ord
      $1!ge;
      # $list[$count] =~ s/\@/\&\#64;/g;
      $count++;
      }
      }


      Now that we have passed @list to char_to_html() let's
      loop over it instead of using a count:

      sub char_to_html {
      my @array = @_;
      foreach my $field ( @array ) {
      $field =~ s/\&/\&\#38;/g;
      $field =~ s!([\$"%()*/:?[^\]{|}~<>\\])!sprintf '&#%d;', ord $1!ge;
      # $field =~ s/\@/\&\#64;/g;
      return @array;
      }

      And we could rid ourselves of the $field variable and
      clean up the other regexes:

      sub char_to_html {
      my @array = @_;
      foreach ( @array ) {
      s/&/&/g;
      s!([\$"%()*/:?[^\]{|}~<>\\])!
      sprintf '&#%d;', ord $1!gex;
      # s/@/@/g;
      return @array;
      }

      As for getting everything into @list:

      my @list;
      push @list, $foo->param('Field1') || 'nil';
      push @list, $foo->param('Field2') || 'nil';
      push @list, $foo->param('Field3') || 'nil';
      push @list, $foo->param('Field4') || 'nil';

      might work. Or:

      my @list;
      foreach ( qw| Field1 Field2 Field3 Field4 | ) {
      push @list, $foo->param($_) || 'nil';
      }

      Or, if you're a map fan:
      my @list = map {$foo->param($_) || 'nil'}
      qw| Field1 Field2 Field3 Field4 |;

      HTH,

      Charles K. Clarkson
      --
      Head Bottle Washer,
      Clarkson Energy Homes, Inc.
      Small commercial and residential rehabilitation specialists.
      254 968-8328

      CJ Web Work - Solutions for Real Estate Investors.
      972 216-4952





      Unsubscribing info is here:
      http://help.yahoo.com/help/us/groups/groups-32.html

      Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/





      ---
      Outgoing mail is certified Virus Free.
      Checked by AVG anti-virus system (http://www.grisoft.com).
      Version: 6.0.373 / Virus Database: 208 - Release Date: 7/1/02
    Your message has been successfully submitted and would be delivered to recipients shortly.