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

Re: Pattern matching in an array

Expand Messages
  • Charles K. Clarkson
    ... 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 ... Congratulations! There s more to learn
    Message 1 of 9 , Jul 1 7:14 AM
    • 0 Attachment
      "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
    • James Colannino
      Hey everyone. I have a quick question. I know that in a scalar variable, I can do something like the following: if ($scalar =~ m/string/) {...}; Can I also
      Message 2 of 9 , Oct 13, 2005
      • 0 Attachment
        Hey everyone. I have a quick question. I know that in a scalar
        variable, I can do something like the following:

        if ($scalar =~ m/string/) {...};

        Can I also do something like this?

        if (@array =~ m/string/) {...};

        My thinking is that, since I'm going to have multiple strings in the
        array, I can check to see if "string" is found within any of the strings
        in the array rather than just in one scalar value. However, I'm not
        sure if this is syntactically correct or not. Thanks in advance.

        James
      • acummingsus
        ... wrote: [ . . ] ... What result did you get when you tried that? ... strings ... But there s also: what the if
        Message 3 of 9 , Oct 13, 2005
        • 0 Attachment
          --- In perl-beginner@yahoogroups.com, "James Colannino"
          <perl-beginner@c...> wrote:
          [ . . ]
          > Can I also do something like this?
          >
          > if (@array =~ m/string/) {...};

          What result did you get when you tried that?

          > My thinking is that, since I'm going to have multiple strings in the
          > array, I can check to see if "string" is found within any of the
          strings
          > in the array rather than just in one scalar value. However, I'm not
          > sure if this is syntactically correct or not. Thanks in advance.

          But there's also: what the if does/needs/**constrains_it_to**

          If I'm not mistaken, the if makes the context be: scalar context

          If I'm not mistaken, when placed into a scalar context, an array, then
          what will returned out of the array is the number of array items:
          array[0], array[1]. array[2], array[3], etc. (in this case four: 0, 1,
          2, 3

          You weren't looking to check 0, 1, 2, 3, 4 were you?

          So, likely you'd need to iterate, thus checking each item one at a time:

          foreach ( @array ) {
          if ( /string/ ) {...}
          } # end

          --
          Alan.
        • Charles K. Clarkson
          ... Let perl help you. Turn on diagnostics. use strict; use warnings; use diagnostics; my @colors_values = map { $_ * 10 } 0 .. 9; print HTH, n n if
          Message 4 of 9 , Oct 13, 2005
          • 0 Attachment
            James Colannino <> wrote:

            : if (@array =~ m/string/) {...};
            :
            : My thinking is that, since I'm going to have multiple strings in
            : the array, I can check to see if "string" is found within any of
            : the strings in the array rather than just in one scalar value.
            : However, I'm not sure if this is syntactically correct or not.

            Let perl help you. Turn on diagnostics.

            use strict;
            use warnings;

            use diagnostics;

            my @colors_values = map { $_ * 10 } 0 .. 9;

            print "HTH,\n\n" if @colors_values =~ m/10/;

            __END__

            I got this. Note the advice in the last sentence.

            Applying pattern match (m//) to @array will act on scalar(@array) at bb.pl
            line
            10 (#1)
            (W misc) The pattern match (//), substitution (s///), and
            transliteration (tr///) operators work on scalar values. If you apply
            one of them to an array or a hash, it will convert the array or hash to
            a scalar value -- the length of an array, or the population info of a
            hash -- and then work on that scalar value. This is probably not what
            you meant to do. See perlfunc/grep and perlfunc/map for
            alternatives.

            HTH,

            Charles K. Clarkson
            --
            Mobile Homes Specialist
            254 968-8328
          • aditya dholi
            Hi, I am not sure whether you are looking for a number of accurances for the pattern or what in the strings... If so then this might help you. # ! usr bin perl
            Message 5 of 9 , Oct 13, 2005
            • 0 Attachment
              Hi,

              I am not sure whether you are looking for a number of accurances for the pattern or what in the strings... If so then this might help you.

              # !\usr\bin\perl
              $a = 1;
              @b = (1,6,3,1,5);

              $s = grep(/$a/,@b);
              print "$s\n";

              Will give the count of occurances.....

              Regards,
              Aditya.

              "Charles K. Clarkson" <cclarkson@...> wrote:
              James Colannino <> wrote:

              : if (@array =~ m/string/) {...};
              :
              : My thinking is that, since I'm going to have multiple strings in
              : the array, I can check to see if "string" is found within any of
              : the strings in the array rather than just in one scalar value.
              : However, I'm not sure if this is syntactically correct or not.

              Let perl help you. Turn on diagnostics.

              use strict;
              use warnings;

              use diagnostics;

              my @colors_values = map { $_ * 10 } 0 .. 9;

              print "HTH,\n\n" if @colors_values =~ m/10/;

              __END__

              I got this. Note the advice in the last sentence.

              Applying pattern match (m//) to @array will act on scalar(@array) at bb.pl
              line
              10 (#1)
              (W misc) The pattern match (//), substitution (s///), and
              transliteration (tr///) operators work on scalar values. If you apply
              one of them to an array or a hash, it will convert the array or hash to
              a scalar value -- the length of an array, or the population info of a
              hash -- and then work on that scalar value. This is probably not what
              you meant to do. See perlfunc/grep and perlfunc/map for
              alternatives.

              HTH,

              Charles K. Clarkson
              --
              Mobile Homes Specialist
              254 968-8328



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



              SPONSORED LINKS
              Basic programming language C programming language Computer programming languages The c programming language C programming language List of programming languages

              ---------------------------------
              YAHOO! GROUPS LINKS


              Visit your group "perl-beginner" on the web.

              To unsubscribe from this group, send an email to:
              perl-beginner-unsubscribe@yahoogroups.com

              Your use of Yahoo! Groups is subject to the Yahoo! Terms of Service.


              ---------------------------------




              ---------------------------------
              Yahoo! Music Unlimited - Access over 1 million songs. Try it free.

              [Non-text portions of this message have been removed]
            • Jeff 'japhy' Pinyan
              ... You re mistaken once. Yes, an if statement enforces scalar context upon its conditional, but that is NOT why the array is placed in scalar context. The
              Message 6 of 9 , Oct 13, 2005
              • 0 Attachment
                On Oct 13, acummingsus said:

                > If I'm not mistaken, the if makes the context be: scalar context
                >
                > If I'm not mistaken, when placed into a scalar context, an array, then
                > what will returned out of the array is the number of array items:
                > array[0], array[1]. array[2], array[3], etc. (in this case four: 0, 1,
                > 2, 3

                You're mistaken once. Yes, an if statement enforces scalar context upon
                its conditional, but that is NOT why the array is placed in scalar
                context. The array is in scalar context because the =~ operator requires
                a scalar as its left-hand operand.

                --
                Jeff "japhy" Pinyan % How can we ever be the sold short or
                RPI Acacia Brother #734 % the cheated, we who for every service
                http://www.perlmonks.org/ % have long ago been overpaid?
                http://princeton.pm.org/ % -- Meister Eckhart
              • Shawn Corey
                ... You would use the grep inside the if statement: if( grep { /string/ } @array ){ ... } You would use the map for substitutions and transliterations. If you
                Message 7 of 9 , Oct 13, 2005
                • 0 Attachment
                  Charles K. Clarkson wrote:
                  > James Colannino <> wrote:
                  >
                  > : if (@array =~ m/string/) {...};
                  > :
                  > : My thinking is that, since I'm going to have multiple strings in
                  > : the array, I can check to see if "string" is found within any of
                  > : the strings in the array rather than just in one scalar value.
                  > : However, I'm not sure if this is syntactically correct or not.
                  >
                  > Let perl help you. Turn on diagnostics.
                  >
                  > use strict;
                  > use warnings;
                  >
                  > use diagnostics;
                  >
                  > my @colors_values = map { $_ * 10 } 0 .. 9;
                  >
                  > print "HTH,\n\n" if @colors_values =~ m/10/;
                  >
                  > __END__
                  >
                  > I got this. Note the advice in the last sentence.
                  >
                  > Applying pattern match (m//) to @array will act on scalar(@array) at bb.pl
                  > line
                  > 10 (#1)
                  > (W misc) The pattern match (//), substitution (s///), and
                  > transliteration (tr///) operators work on scalar values. If you apply
                  > one of them to an array or a hash, it will convert the array or hash to
                  > a scalar value -- the length of an array, or the population info of a
                  > hash -- and then work on that scalar value. This is probably not what
                  > you meant to do. See perlfunc/grep and perlfunc/map for
                  > alternatives.

                  You would use the grep inside the if statement:

                  if( grep { /string/ } @array ){
                  ...
                  }

                  You would use the map for substitutions and transliterations. If you
                  want to extract part of the pattern, you would use a for loop:

                  for my $item ( @array ){
                  if( $item =~ /(\d+)/ ){
                  my $number = $1;
                  ...
                  }
                  }

                  __END__

                  See `perldoc perlfunc` `perldoc -f grep` `perldoc -f map`.


                  --- Shawn
                • acummingsus
                  ... [ . . ] ... upon ... Choppy writing and omission be my sin since I had awareness of that about the =~ operator. Thank you. I ll work at exercising
                  Message 8 of 9 , Oct 13, 2005
                  • 0 Attachment
                    --- In perl-beginner@yahoogroups.com, Jeff 'japhy' Pinyan <japhy@p...>
                    wrote:
                    > On Oct 13, acummingsus said:
                    > > If I'm not mistaken, the if makes the context be: scalar context
                    > >
                    > > If I'm not mistaken, when placed into a scalar context, an array, then
                    > > what will returned out of the array is the number of array items:
                    [ . . ]
                    > You're mistaken once. Yes, an if statement enforces scalar context
                    upon
                    > its conditional, but that is NOT why the array is placed in scalar
                    > context. The array is in scalar context because the =~ operator
                    > requires a scalar as its left-hand operand.

                    Choppy writing and omission be my sin since I had awareness of that
                    about the =~ operator. Thank you. I'll work at exercising
                    more/greater caution.

                    There's undoubtedly many various different expertise levels of
                    newbie/beginner perusing this emailing list. Thus the importance of
                    quality in communication.

                    # com for communication
                    my $com = _______ (fill in the blank);
                    unless( $com eq quality ) {
                    print "eek, this garble is confusing the beginner ";
                    print "and making it more difficult ";
                    print "for the beginner to learn.\n";
                    }

                    On another note, I tinkered a bit more with this thread's topic. I
                    tested to see if I could match an array indice using scalar() as in
                    the enclosed code. But the only thing that matches in my example is a
                    6 which is the total number of elements in the array.

                    #!/usr/bin/perl
                    use strict;
                    use warnings;

                    use diagnostics;
                    my @colors = qw(red blue white black orange green);

                    foreach( @colors ) {
                    print "$_\n";
                    print "HTH, \$_ is $_\n" if /blue/;
                    print "$_ matches $_\n" if /blue/;
                    }
                    print "---------------\n";
                    if( scalar(@colors) =~ /6/ ) {
                    print "yes a match: ";
                    print scalar(@colors), "\n";
                    print "indices 0 to 5\n";
                    print "its a 6 item array\n";
                    } else {
                    print "no match\n";
                    }
                    print "---------------\n";
                    print scalar(@colors), "\n";
                    print $colors[5], "\n\n";
                    # end

                    Alan.
                  Your message has been successfully submitted and would be delivered to recipients shortly.