Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

split with separators but dont include in the array

by anniyan (Monk)
on Oct 17, 2005 at 15:23 UTC ( [id://500743]=perlquestion: print w/replies, xml ) Need Help??

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

I have a string like

$str = '<chap&&<book||<table&&<list';

I want to split that with && and || but i dont want to include those && and || in the array.

If i use the following code, it splits correctly but it stores the && and || in the array.

@arr = split /(?=(&&|\|\|))/, $str;

How to do this?

Regards,
Anniyan
(CREATED in HELL by DEVIL to s|EVILS|GOODS|g in WORLD)

Replies are listed 'Best First'.
Re: split with separators but dont include in the array
by ikegami (Patriarch) on Oct 17, 2005 at 15:29 UTC

    We start with:

    @arr = split /(?=(&&|\|\|))/, $str; # @arr = ('<chap', '&&', '&&<book', '||', '||<table', '&&', '&&<list') +;

    Use non-capturing (?:...) instead of the capturing (...):

    @arr = split /(?=(?:&&|\|\|))/, $str; # @arr = ('<chap', '&&<book', '||<table', '&&<list');

    But neither are needed here

    @arr = split /(?=&&|\|\|)/, $str; # @arr = ('<chap', '&&<book', '||<table', '&&<list');

    Are you sure you want to use (?=...)?

    @arr = split /&&|\|\|/, $str; # @arr = ('<chap', '<book', '<table', '<list');
Re: split with separators but dont include in the array
by Roy Johnson (Monsignor) on Oct 17, 2005 at 15:29 UTC
    You're using lookahead and capturing parentheses. You want an unparenthesized expression so the separators are discarded.
    @arr = split /&&|\|\|/, $str;

    Caution: Contents may have been coded under pressure.

      Roy Johnson and ikegami thanks for your quick replies. Here i have one question. First i tried like the following.

      @arr = split /(&&|\|\|)/, $str;

      But it included && and || in the array. Then only i went for lookahead option.

      But as per yours reply it works fine if i remove that extra grouping.

      @arr = split /&&|\|\|/, $str;

      Why is it so? Could you please explain. Then if there is many separators how to with that?

      Regards,
      Anniyan
      (CREATED in HELL by DEVIL to s|EVILS|GOODS|g in WORLD)

        Anything in capturing (plain) parentheses will be returned as a separate item in the split results. If you need parentheses for grouping, use non-capturing parentheses, which open with (?: instead of just (.

        No matter how many alternative separators you have, you don't need parentheses at all unless the alternatives are only part of the separator and you need to "factor out" common substrings. For example, if your valid separators were "foo&&", "foo||", and "++", you could split on

        /foo(?:&&|\|\|)|++/

        Caution: Contents may have been coded under pressure.
        @arr = split /(&&|\|\|)/, $str;
        But it included && and || in the array.

        That's because you used capturing parentheses.

        Then if there is many separators how to with that?

        You use the pipe "|" character to separate multiple options, like so:
        @arr = split /foo|bar|meh/, $str;
        That would split the string on any occurrences of "foo", "bar" or "meh" without including them in the resultant list.
        This may not be clear in your original example, as one of the strings you are splitting on is a double-pipe "||", so the escaping of those adds a bit of "noise" to the split expression :)
        The manual (split in this case) can usually dissipate such doubts:
        If the PATTERN contains parentheses, additional list elements are created from each matching sub- string in the delimiter. + split(/([,-])/, "1-10,20", 3); + produces the list value + (1, '-', 10, ',', 20)

        Flavio
        perl -ple'$_=reverse' <<<ti.xittelop@oivalf

        Don't fool yourself.
Re: split with separators but dont include in the array
by Limbic~Region (Chancellor) on Oct 17, 2005 at 15:27 UTC
    anniyan,
    Sometimes it is important to start out with functional code and then work on improving it to be "right". Have you considered making it two steps?
    my @matches = grep { $_ !~ /(\&\&|\|\|)/ } split /(\&\&|\|\|)/, $str;
    This obviously isn't the way you want to leave the final code but it is better to having something that works that you are unhappy with then something that doesn't work at all. You can always improve.

    Cheers - L~R

    Commentary after the code snippet added

      Thanks, Yes it works fine, is it not possible to write with lookahead and look behind?

      Regards,
      Anniyan
      (CREATED in HELL by DEVIL to s|EVILS|GOODS|g in WORLD)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://500743]
Approved by Samy_rio
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (4)
As of 2024-04-25 14:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found