http://www.perlmonks.org?node_id=805781

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

Hi,
I will have a line of text in one of the two forms like below
my $lineshapesline1 = 'SHAPES GREEN1;SIZE 240 500 340 930;SIZE 350 500 + 240 590;SIZE 295 390 015 490;SIZE 350 210 760 300;SHAPES GREEN2;SIZE + 450 310 680 690;SIZE 450 110 680 490;SIZE 215 800 560 900;';
or
my $lineobsshapesline2 = 'SHAPES GREEN;SIZE 240 500 340 930;SIZE 350 5 +00 240 590;SIZE 295 390 015 490;SIZE 350 210 760 300;SHAPES BLUE;SIZE + 450 310 680 690;SIZE 450 110 680 490;SIZE 215 800 560 900;';

(1) How do I "push" into an array each of the "SHAPES" with out using Perl's split function?
(2)I want my array to contain elements in the following way:
$arrayelement[0] = SHAPES GREEN;SIZE 240 500 340 930;SIZE 350 500 240 +590;SIZE 295 390 015 490;SIZE 350 210 760 300; $arrayelement[1] = SHAPES BLUE;SIZE 450 310 680 690;SIZE 450 110 680 4 +90;SIZE 215 800 560 900;'; ... ...

Replies are listed 'Best First'.
Re: splitting line without split
by keszler (Priest) on Nov 08, 2009 at 16:10 UTC
    I don't understand why you don't like split, but maybe a regex will be more to your liking?
    use strict; my $lineshapesline1 = 'SHAPES GREEN1;SIZE 240 500 340 930;SIZE 350 500 + 240 590;SIZE 295 390 015 490;SIZE 350 210 760 300;SHAPES GREEN2;SIZE + 450 310 680 690;SIZE 450 110 680 490;SIZE 215 800 560 900;'; my @array; while ( $lineshapesline1 =~ /(SHAPES.*?)(?=SHAPES|$)/g ) { push @array, $1; } print "$_\n" for @array; __END__ SHAPES GREEN1;SIZE 240 500 340 930;SIZE 350 500 240 590;SIZE 295 390 0 +15 490;SIZE 350 210 760 300; SHAPES GREEN2;SIZE 450 310 680 690;SIZE 450 110 680 490;SIZE 215 800 5 +60 900;
Re: splitting line without split
by ikegami (Patriarch) on Nov 08, 2009 at 17:40 UTC
    my @a = /((?:[^;]|;(?!SHAPES |\z))+;)/g;
Re: splitting line without split
by johngg (Canon) on Nov 08, 2009 at 17:34 UTC

    If you are dead set against split and a regex you could use index and substr.

    use strict; use warnings; use Data::Dumper; my @shapeLines = ( q{SHAPES GREEN1;SIZE 240 500 340 930;SIZE 350 500 240 590;SIZE 295 +390 015 490;SIZE 350 210 760 300;SHAPES GREEN2;SIZE 450 310 680 690;S +IZE 450 110 680 490;SIZE 215 800 560 900;}, q{SHAPES GREEN;SIZE 240 500 340 930;SIZE 350 500 240 590;SIZE 295 3 +90 015 490;SIZE 350 210 760 300;SHAPES BLUE;SIZE 450 310 680 690;SIZE + 450 110 680 490;SIZE 215 800 560 900;}, ); my @shapes = (); foreach my $shapeLine ( @shapeLines ) { my @posns = (); my $posn = -1; while ( ( $posn = index( $shapeLine, q{SHAPES}, $posn ) ) > -1 ) { push @posns, $posn; $posn ++; } foreach my $posnIdx ( 0 .. $#posns ) { push @shapes, substr $shapeLine, $posns[ $posnIdx ], $posnIdx == $#posns ? length( $shapeLine ) - $posns[ $posnIdx ] : $posns[ $posnIdx + 1 ] - $posns[ $posnIdx ]; } } print Data::Dumper->Dumpxs( [ \ @shapes ], [ qw{ *shapes } ] )
    $ ./spw805781 @shapes = ( 'SHAPES GREEN1;SIZE 240 500 340 930;SIZE 350 500 240 590;S +IZE 295 390 015 490;SIZE 350 210 760 300;', 'SHAPES GREEN2;SIZE 450 310 680 690;SIZE 450 110 680 490;S +IZE 215 800 560 900;', 'SHAPES GREEN;SIZE 240 500 340 930;SIZE 350 500 240 590;SI +ZE 295 390 015 490;SIZE 350 210 760 300;', 'SHAPES BLUE;SIZE 450 310 680 690;SIZE 450 110 680 490;SIZ +E 215 800 560 900;' ); $

    I hope this is helpful.

    Cheers,

    JohnGG

Re: splitting line without split
by Bloodnok (Vicar) on Nov 08, 2009 at 17:21 UTC
    Is it just me, or is there a faint aroma of homework about this post ??

    Having said that, your question makes no sense since the 2 array elements specified in your required result contain but one i.e. mismatched, single quote - so its unclear whether you require 2 array elements, each containing a string, or 2 array elements, each containing an array of elements - in either case, it [the spec] constitutes a bad spec!

    A user level that continues to overstate my experience :-))
      Well you seem to be having a wrong "aroma" experience on this one!

      FWIW, this is not a homework. It is a major project and I am new to Perl/RE. So when I get stuck in coding, I occasionally post here asking for help because I always get excellent and superb help each time I seek answers. Moreover, almost everyone on this site seem to be super helpful.

      Appreciate your comments any way :)

      J.
        That code works too for the part I was concerned with. Appreciate all the help.
        J.
        Pardon?

        You haven't 'given me any code'...methinx you may well have provided a post on the wrong thread.

        A user level that continues to overstate my experience :-))
Re: splitting line without split
by CountZero (Bishop) on Nov 08, 2009 at 20:59 UTC
    Meanwhile you have received several examples of splitting without using split, proof of the fact that TIMTOWTDI!

    But, why can't you use split in your code?

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      Hi CountZero,
      Yes, like I mentioned, I always receive excellent suggestions from here. That is what makes this website a great place to learn from others' experiences.
      Unfortunately, the placed I work for is not that friendly to Perl or Linux usage. My workplace has some other old utilities/methodologies and people here have no interest in learning another new tool - Perl or knowing the much better solutions Perl offers. Long story short, I just have to have an alternative ready to show that Perl can do what our internal tool can do (with out having to use split)
      J.
        I know the feeling -- same thing here!

        But just because of that, I like to show the power of Perl and split is such a wonderful function: simple yet powerful and everybody can understand how it works, even without knowing Perl (of course if you do not go too deep into details).

        Even PHP now has deprecated their split function in favour of preg_split which is a Perl Compatible Regular Expression split! Take that PHP. Perhaps they can go one step further and deprecate the whole of PHP and replace it by Perl. :-)

        CountZero

        A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: splitting line without split
by graff (Chancellor) on Nov 09, 2009 at 02:49 UTC
    I'm a little confused by item "(2)", because the two lines that look like code (for the two elements of an array called "@arrayelement" are syntax errors. Did you intend to treat SHAPES GREEN;SIZE 240 ... 300 as a single quoted string (and likewise for the second element)?

    Also, you didn't mention it specifically, but are the two elements from item "(2)" derived only from the second input line? Would the first input line produce two output array elements like this?

    $elem[0] = "SHAPES GREEN1;SIZE 240 500 340 930;SIZE 350 500 240 590;SI +ZE 295 390 015 490;SIZE 350 210 760 300;"; $elem[1] = "SHAPES GREEN2;SIZE 450 310 680 690;SIZE 450 110 680 490;SI +ZE 215 800 560 900;";
    If I have that right, then it's true that using "split()" would be a bit clunky, and a regex match would make more sense. For the patterns given, I'd do it like this:
    my @matches = ( $inp_line =~ /(SHAPES \w+;(?:SIZE[ \d+])+;)/g );
    Or if you want a bunch of matches from various input lines all pushed onto the same array:
    my @matches; for ( @inp_lines ) { push @matches, ( /(SHAPES \w+;(?:SIZE[ \d+])+;)/g ); }
    Yet another way to look at the problem: if the input lines are being read from some list file (or stdin), such that each line originally has a line-feed at the end, then what you are doing is, in a way, the same as inserting a line-feed in the middle of each line:
    s/(?<=\d;)(?=SHAPES )/\n/; # using "look-behind" and "look-ahead # now just split on "\n"...
Re: splitting line without split
by garbage777 (Acolyte) on Nov 09, 2009 at 05:24 UTC
    Thanks to every one for your help.