Thread: REGEX help

    #1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2013
    Posts
    37
    Rep Power
    1

    REGEX help


    I need help with REGEX I'm pretty sure. This is my text file :

    g 7 g 3 f 3 t 4 t 3 h 2 f 3 f 10

    My code is supposed to combine the g7 and g 3 into g 10, the f3 and f 10 into f 13....etc. And print the whole array out with everything added together. I don't even know how to go about doing that. This is my code:


    Code:
    #!/usr/bin/env perl
    use warnings;
    use strict;
    
    my @count_hash;   
    
    while (<>){
                @count_hash  = split / /, $_;   
            }
    print "@count_hash\n";
    How could I go about checking for tags and adding them together? Do I use REGEX?
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Apr 2009
    Posts
    1,932
    Rep Power
    1225
    Code:
    #!/usr/bin/perl
    
    use strict;
    use warnings;
    use Data::Dumper;
    
    my $str = 'g 7 g 3 f 3 t 4 t 3 h 2 f 3 f 10';
    my %groups;
    
    $groups{$1} += $2 while $str =~ /([a-z]) (\d+)/g;
    print Dumper \%groups;
    Outputs:
    Code:
    $VAR1 = {
              'h' => '2',
              'g' => '10',
              'f' => '16',
              't' => '7'
            };

    Comments on this post

    • qabulin agrees : I liked you're usage of the hash. :)
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2013
    Posts
    37
    Rep Power
    1
    Originally Posted by FishMonger
    Code:
    #!/usr/bin/perl
    
    use strict;
    use warnings;
    use Data::Dumper;
    
    my $str = 'g 7 g 3 f 3 t 4 t 3 h 2 f 3 f 10';
    my %groups;
    
    $groups{$1} += $2 while $str =~ /([a-z]) (\d+)/g;
    print Dumper \%groups;
    Outputs:
    Code:
    $VAR1 = {
              'h' => '2',
              'g' => '10',
              'f' => '16',
              't' => '7'
            };
    Thanks for the input fish. So there is no way to do that with just an array, split and REGEX? The preceding code doesn't work, but something along these lines:

    Code:
    my @count_hash;                   
    
    while (<>){   
            if(/([A-Z])(" ")([A-Z])/){ 
                   $Val = $1 + $3 }
    
    
            @count_hash  = split / /, $_;
            }
    print "@count_hash\n";
    Something along those lines?? Or, if there is any synthax that lets me check an array for every other element, and sees if they are equal or not, than adds to specific elements of an array.
  6. #4
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2013
    Posts
    2
    Rep Power
    0
    Originally Posted by seedofwinter
    So there is no way to do that with just an array, split and REGEX?
    I really liked FishMonger's example and thought it concise and quite useful. However, if it is an array you are specifically hunting for, and assuming you are using a filename as your $ARGV[0], maybe this is useful?
    Code:
    #!/usr/bin/perl
    use strict;
    use warnings;
    
    my @array = map {
      s/([a-z]) (\d+)/$1$2/g;
      split;
    } <>;
    
    print "@array\n";    # pick the output you deem appropriate
    In the regex chunk of your example, you do not really need this thing: (" "). Notice in my regex I just leave a space. Using a global substitution s///g then cuts out that space between each letter/number pair. This will clean up your latest regex handling some.

    Cheers!
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2013
    Posts
    37
    Rep Power
    1
    Originally Posted by qabulin
    I really liked FishMonger's example and thought it concise and quite useful. However, if it is an array you are specifically hunting for, and assuming you are using a filename as your $ARGV[0], maybe this is useful?
    Code:
    #!/usr/bin/perl
    use strict;
    use warnings;
    
    my @array = map {
      s/([a-z]) (\d+)/$1$2/g;
      split;
    } <>;
    
    print "@array\n";    # pick the output you deem appropriate
    In the regex chunk of your example, you do not really need this thing: (" "). Notice in my regex I just leave a space. Using a global substitution s///g then cuts out that space between each letter/number pair. This will clean up your latest regex handling some.

    Cheers!
    Thanks a lot man. And I agree, it does work and seems a lot simpler. But I was told it could be done with arrays and split and some REGEX, and I it has continuously elluded me.
  10. #6
  11. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2013
    Posts
    2
    Rep Power
    0
    One other thing if I may, seedofwinter...

    I actually goofed and forgot to add FishMonger's important bit that satisfies your request to combine:
    My code is supposed to combine the g7 and g 3 into g 10, the f3 and f 10 into f 13....etc.
    A thousand pardons.
    Code:
    #!/usr/bin/perl
    use strict;
    use warnings;
    use Data::Dumper;
    
    my $str = <>;
    my %groups;
    # combines like terms...
    $groups{$1} += $2 while $str =~ /([a-z]) (\d+)/g;
    
    my @array;
    # builds your array...
    @array = map { "$_$groups{$_}" } keys %groups;
    
    print "@array\n";    # pick the output you deem appropriate
    To do it with JUST arrays, split and regex seems like you have to intentionally work harder to reach the same goal without a hash at all.
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2012
    Posts
    830
    Rep Power
    496
    If you really want to do it directly into an array, you could in theory adapt Fishmonger's solution and do something along the lines of the following session under the Perl debugger:

    Code:
      DB<1>  $str = 'g 7 g 3 f 3 t 4 t 3 h 2 f 3 f 10';
    
      DB<2> $groups[ord $1] += $2 while $str =~ /([a-z]) (\d+)/g;
    
      DB<3> for (0..$#groups) { print chr ($_), "\t$groups[$_]\n" if defined $groups[$_] }
    f       16
    g       10
    h       2
    t       7
    However, this is using two additional operators, chr and ord, and this solution is quite messy: it creates an array of 117 elements, in which only four are defined and useful. The hash solution is really better in my opinion.
  14. #8
  15. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2013
    Posts
    37
    Rep Power
    1
    Originally Posted by qabulin
    One other thing if I may, seedofwinter...

    I actually goofed and forgot to add FishMonger's important bit that satisfies your request to combine:

    A thousand pardons.
    Code:
    #!/usr/bin/perl
    use strict;
    use warnings;
    use Data::Dumper;
    
    my $str = <>;
    my %groups;
    # combines like terms...
    $groups{$1} += $2 while $str =~ /([a-z]) (\d+)/g;
    
    my @array;
    # builds your array...
    @array = map { "$_$groups{$_}" } keys %groups;
    
    print "@array\n";    # pick the output you deem appropriate
    To do it with JUST arrays, split and regex seems like you have to intentionally work harder to reach the same goal without a hash at all.

    That's incredible. Thank you so much. No need to pardon yourself, I'm just happy you helping me out.
  16. #9
  17. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2012
    Posts
    830
    Rep Power
    496
    OK, never mind.

IMN logo majestic logo threadwatch logo seochat tools logo