Question about range of Lines

Discussion in 'Perl Misc' started by mauro papandrea, Sep 15, 2011.

  1. Given this simple file:

    cat t1

    Sunday
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
    Saturday

    with

    perl -ne 'print if /Tuesday/ .. /Friday/;' t1

    I can get:

    Tuesday
    Wednesday
    Thursday
    Friday


    Is there a simple way to modify the range selection in order to get all
    the lines but the last in the range?
    Namely, getting this output:

    Tuesday
    Wednesday
    Thursday

    An idea could be to push back last line but I do not know how to do that.

    Thank you

    Regards

    Mauro

    PS this is an oversimplified case for the sake of simplicity
    mauro papandrea, Sep 15, 2011
    #1
    1. Advertising

  2. mauro papandrea

    lcof Guest

    The Thu, 15 Sep 2011 09:28:42 +0200, mauro papandrea wrote :

    > Given this simple file:
    >
    > cat t1
    >
    > Sunday
    > Monday
    > Tuesday
    > Wednesday
    > Thursday
    > Friday
    > Saturday
    >
    > with
    >
    > perl -ne 'print if /Tuesday/ .. /Friday/;' t1
    >
    > I can get:
    >
    > Tuesday
    > Wednesday
    > Thursday
    > Friday
    >
    >
    > Is there a simple way to modify the range selection in order to get all
    > the lines but the last in the range?
    > Namely, getting this output:
    >
    > Tuesday
    > Wednesday
    > Thursday
    >
    > An idea could be to push back last line but I do not know how to do
    > that.
    >
    > Thank you
    >
    > Regards
    >
    > Mauro
    >
    > PS this is an oversimplified case for the sake of simplicity


    You mean, something like this ?

    perl -ne 'while(<>) { push @a, $_ if /Tuesday/ .. /Friday/; } pop @a;
    print @a' < t1
    lcof, Sep 15, 2011
    #2
    1. Advertising

  3. mauro papandrea

    Mauro Guest

    On 15/09/2011 14.17, lcof wrote:
    > You mean, something like this ?
    >
    > perl -ne 'while(<>) { push @a, $_ if /Tuesday/ .. /Friday/; } pop @a;
    > print @a'< t1


    Thank you

    However it is not so clear how it works; I thought that -n option was
    supposed to add an implicit loop and there were no need to add a further
    while (<>), not to say anything about reading from a redirection instead
    of reading directly the file.

    Regards

    Mauro
    Mauro, Sep 15, 2011
    #3
  4. mauro papandrea

    Mauro Guest

    On 15/09/2011 14.34, Tad McClellan wrote:
    >
    > perl -ne '$a = 1 if /Tuesday/; $a = 0 if /Friday/; print if $a' t1
    >


    Thanl you

    This appears much clearer, I hope to be able to adapt it to solve my
    original problem, that was slightly different ( I am afraid I
    oversimplified too much ).

    Regards
    Mauro, Sep 15, 2011
    #4
  5. mauro papandrea

    Lucien Coffe Guest

    Mauro wrote :

    > On 15/09/2011 14.17, lcof wrote:
    >> You mean, something like this ?
    >>
    >> perl -ne 'while(<>) { push @a, $_ if /Tuesday/ .. /Friday/; } pop @a;
    >> print @a'< t1

    >
    > Thank you
    >
    > However it is not so clear how it works; I thought that -n option was
    > supposed to add an implicit loop and there were no need to add a further
    > while (<>), not to say anything about reading from a redirection instead
    > of reading directly the file.
    >
    > Regards
    >
    > Mauro


    Sure, I did not took off the -n option after copy-pasting your line, so I
    used a redirection. Consider the following :

    perl -e 'while(<>) { push @a, $_ if /Tuesday/../Friday/ } pop @a; print
    @a' t1

    Good luck with your algorithm. Btw Tad McClellan's solution is much more
    efficient.

    --
    perl -e 's;;{]``*%)}`_^[&)/#%(`&;;y;%^)([]/*#&`_{};.
    \100acghiklmopsz;;print'
    Lucien Coffe, Sep 15, 2011
    #5
  6. mauro papandrea

    Mauro Guest

    > Sure, I did not took off the -n option after copy-pasting your line, so I
    > used a redirection. Consider the following :
    >
    > perl -e 'while(<>) { push @a, $_ if /Tuesday/../Friday/ } pop @a; print
    > @a' t1
    >
    > Good luck with your algorithm. Btw Tad McClellan's solution is much more
    > efficient.


    Well, now it is much clearer; just wondering why this do not work:

    perl -ne '{ push @a, $_ if /Tuesday/../Friday/ } pop @a; print @a' t1

    Regards

    Mauro
    Mauro, Sep 15, 2011
    #6
  7. mauro papandrea

    Lucien Coffe Guest

    Mauro wrote :

    >> Sure, I did not took off the -n option after copy-pasting your line, so
    >> I used a redirection. Consider the following :
    >>
    >> perl -e 'while(<>) { push @a, $_ if /Tuesday/../Friday/ } pop @a; print
    >> @a' t1
    >>
    >> Good luck with your algorithm. Btw Tad McClellan's solution is much
    >> more efficient.

    >
    > Well, now it is much clearer; just wondering why this do not work:
    >
    > perl -ne '{ push @a, $_ if /Tuesday/../Friday/ } pop @a; print @a' t1


    This gives :

    while(<>) {
    {
    push @a, $_ if /Tuesday/../Friday/
    }
    pop @a;
    print @a
    }

    That's not what you want. You have to use an END block to get the pop and
    print instructions out of the while loop, like this :

    perl -ne 'push @a, $_ if /Tuesday/../Friday/; END { pop @a; print @a }' t1

    >
    > Regards
    >
    > Mauro


    { push @a, $_ if /Tuesday/../Friday/ } pop @a; print @a


    --
    perl -e 's;;{]``*%)}`_^[&)/#%(`&;;\
    y;%^)([]/*#&`_{};.\100acghiklmopsz;;print'
    Lucien Coffe, Sep 15, 2011
    #7
  8. mauro papandrea

    Mauro Guest

    On 15/09/2011 16.54, Lucien Coffe wrote:
    >> Well, now it is much clearer; just wondering why this do not work:
    >>
    >> perl -ne '{ push @a, $_ if /Tuesday/../Friday/ } pop @a; print @a' t1

    >
    > This gives :
    >
    > while(<>) {
    > {
    > push @a, $_ if /Tuesday/../Friday/
    > }
    > pop @a;
    > print @a
    > }
    >


    Oh, I see, those two {} more ... that is the difference, I missed that

    Thank you for pointing out it to me

    Regards

    Mauro
    Mauro, Sep 15, 2011
    #8
  9. mauro papandrea wrote:
    > Given this simple file:
    >
    > cat t1
    >
    > Sunday
    > Monday
    > Tuesday
    > Wednesday
    > Thursday
    > Friday
    > Saturday
    >
    > with
    >
    > perl -ne 'print if /Tuesday/ .. /Friday/;' t1
    >
    > I can get:
    >
    > Tuesday
    > Wednesday
    > Thursday
    > Friday
    >
    >
    > Is there a simple way to modify the range selection in order to get all
    > the lines but the last in the range?
    > Namely, getting this output:
    >
    > Tuesday
    > Wednesday
    > Thursday


    $ echo "Sunday
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
    Saturday" | perl -ne'print if (/Tuesday/ .. /Friday/) && !/Friday/'
    Tuesday
    Wednesday
    Thursday




    John
    --
    Any intelligent fool can make things bigger and
    more complex... It takes a touch of genius -
    and a lot of courage to move in the opposite
    direction. -- Albert Einstein
    John W. Krahn, Sep 16, 2011
    #9
  10. mauro papandrea

    Mauro Guest

    On 16/09/2011 2.36, John W. Krahn wrote:
    > perl -ne'print if (/Tuesday/ .. /Friday/) && !/Friday/'



    Thank you very much

    Regards

    Mauro
    Mauro, Sep 16, 2011
    #10
  11. On 2011-09-15 12:34, Tad McClellan <> wrote:
    > mauro papandrea <> wrote:
    >> Given this simple file:
    >>
    >> Sunday
    >> Monday
    >> Tuesday
    >> Wednesday
    >> Thursday
    >> Friday
    >> Saturday

    >
    >
    >> Namely, getting this output:
    >>
    >> Tuesday
    >> Wednesday
    >> Thursday

    >
    >
    > perl -ne '$a = 1 if /Tuesday/; $a = 0 if /Friday/; print if $a' t1


    Another solution which avoids the range operator:

    perl -e '$/ = undef; $s = <>; print $s =~ /^(Tuesday.*?)^Friday/sm;' t1

    hp
    Peter J. Holzer, Sep 17, 2011
    #11
  12. mauro papandrea

    Mauro Guest

    > Another solution which avoids the range operator:
    >
    > perl -e '$/ = undef; $s =<>; print $s =~ /^(Tuesday.*?)^Friday/sm;' t1
    >
    > hp
    >


    Thank you, it is a nice idea ( but for too much long files, perhaps ).

    Regards

    Mauro
    Mauro, Sep 19, 2011
    #12
  13. mauro papandrea

    Guest

    On Thu, 15 Sep 2011 09:28:42 +0200, mauro papandrea <> wrote:

    >Given this simple file:
    >
    >cat t1
    >
    >Sunday
    >Monday
    >Tuesday
    >Wednesday
    >Thursday
    >Friday
    >Saturday
    >
    >with
    >
    >perl -ne 'print if /Tuesday/ .. /Friday/;' t1
    >
    >I can get:
    >
    >Tuesday
    >Wednesday
    >Thursday
    >Friday
    >
    >
    >Is there a simple way to modify the range selection in order to get all
    >the lines but the last in the range?
    >Namely, getting this output:
    >
    >Tuesday
    >Wednesday
    >Thursday
    >
    >An idea could be to push back last line but I do not know how to do that.
    >
    >Thank you
    >
    >Regards
    >
    >Mauro
    >
    >PS this is an oversimplified case for the sake of simplicity


    As others mentioned, I would go the simple way using an range operator
    and an additional regex:

    print if (/Tuesday/ .. /Friday/ and !/Tuesday); # not Tuesday
    print if (/Tuesday/ .. /Friday/ and !/Tuesday|Friday/); # not Tuesday nor Friday
    print if (/Tuesday/ .. /Friday/ and !/Friday/); # not Friday

    If you want to use just a range operator, it becomes difficult (untested):

    # not Tuesday
    perl -ne 'print if $st=~/Tuesday/ .. /Friday/; $st=$_' t1

    # not Tuesday nor Friday
    (left as an exersize)

    # not Friday
    perl -e 'do {print if /Tuesday/ .. $st=~/Friday/; $_=$st;} while ($st=<>)' t1


    -sln
    , Sep 19, 2011
    #13
  14. writes:

    > On Thu, 15 Sep 2011 09:28:42 +0200, mauro papandrea <> wrote:

    <snip>
    >>Is there a simple way to modify the range selection in order to get all
    >>the lines but the last in the range?
    >>Namely, getting this output:
    >>
    >>Tuesday
    >>Wednesday
    >>Thursday

    <snip>
    >>PS this is an oversimplified case for the sake of simplicity

    >
    > As others mentioned, I would go the simple way using an range operator
    > and an additional regex:
    >
    > print if (/Tuesday/ .. /Friday/ and !/Tuesday); # not Tuesday
    > print if (/Tuesday/ .. /Friday/ and !/Tuesday|Friday/); # not Tuesday nor Friday


    I think the days of the week, all in order, were just an example. If
    so, then these two are not quite what they seem because they exclude
    extra Tuesdays. Of course, it's possible that the string that starts
    the range never appears in it (in which case all is well) but the
    example may have been oversimplified.

    > print if (/Tuesday/ .. /Friday/ and !/Friday/); # not Friday


    There's no problem here because the end pattern can't appear in the
    range -- by definition. And since this is what the OP asked for, a rang
    and regex does seem like the way to go.

    <snip>
    --
    Ben.
    Ben Bacarisse, Sep 19, 2011
    #14
  15. mauro papandrea

    Guest

    On Mon, 19 Sep 2011 23:02:18 +0100, Ben Bacarisse <> wrote:

    > writes:
    >
    >> On Thu, 15 Sep 2011 09:28:42 +0200, mauro papandrea <> wrote:

    ><snip>
    >>>Is there a simple way to modify the range selection in order to get all
    >>>the lines but the last in the range?
    >>>Namely, getting this output:
    >>>
    >>>Tuesday
    >>>Wednesday
    >>>Thursday

    ><snip>
    >>>PS this is an oversimplified case for the sake of simplicity

    >>
    >> As others mentioned, I would go the simple way using an range operator
    >> and an additional regex:
    >>
    >> print if (/Tuesday/ .. /Friday/ and !/Tuesday); # not Tuesday
    >> print if (/Tuesday/ .. /Friday/ and !/Tuesday|Friday/); # not Tuesday nor Friday

    >
    >I think the days of the week, all in order, were just an example. If
    >so, then these two are not quite what they seem because they exclude
    >extra Tuesdays. Of course, it's possible that the string that starts
    >the range never appears in it (in which case all is well) but the
    >example may have been oversimplified.


    I believe this is a true statement.

    >> print if (/Tuesday/ .. /Friday/ and !/Friday/); # not Friday

    >
    >There's no problem here because the end pattern can't appear in the
    >range -- by definition. And since this is what the OP asked for, a rang
    >and regex does seem like the way to go.
    >


    And this is true too. But, I believe using the range operator in this
    context does not imply a 'Friday' exists in the data, where 'Tuesday'
    must if the condition is satisfied. Thats not saying anything is wrong
    using the range operator like this, just that some extra buffering
    might/might-not be needed. There is usually more to posters questions
    than an academic translation.

    -sln
    , Sep 20, 2011
    #15
  16. mauro papandrea

    Mauro Guest

    On 19/09/2011 21.39, wrote:
    > "but for too much long files, perhaps"
    >
    > I would give this credibility if you can show some code that
    > guarantees there is a 'Friday'.
    >
    > while (<>) {
    > if (/Tuesday/ .. /Friday/) {}
    > }
    >
    > In this case, the operator .. flips true on $_=~/Tuesday/ and remains
    > so until after it finds $_=~/Friday/ or, until the while() is false.
    >
    > I can see why you would be interested in how the range operator
    > works in this case, but don't promote it to something perfect.
    >
    > -sln


    I had expressed that doubt ( about long files ) since, if I understand
    correctly, that solution read the whole file in memory.
    The example I posted was an artificial oversimplified case, just to have
    something concrete to apply code, not the real case ( where there is no
    friday at all ).

    Thank you

    Regards

    Mauro
    Mauro, Sep 20, 2011
    #16
  17. mauro papandrea

    Mauro Guest

    >>
    >> There's no problem here because the end pattern can't appear in the
    >> range -- by definition. And since this is what the OP asked for, a rang
    >> and regex does seem like the way to go.
    >>

    >
    > And this is true too. But, I believe using the range operator in this
    > context does not imply a 'Friday' exists in the data, where 'Tuesday'
    > must if the condition is satisfied. Thats not saying anything is wrong
    > using the range operator like this, just that some extra buffering
    > might/might-not be needed. There is usually more to posters questions
    > than an academic translation.
    >
    > -sln


    As a matter of fact, as I said in the other reply of mine, the original
    problem was quite different, although it was always about a range of lines.
    Perhaps I simplified a bit too much ...

    Regards

    Mauro
    Mauro, Sep 20, 2011
    #17
  18. On 2011-09-19 19:39, <> wrote:
    > On Mon, 19 Sep 2011 11:08:46 +0200, Mauro <> wrote:
    >
    >>> Another solution which avoids the range operator:
    >>>
    >>> perl -e '$/ = undef; $s =<>; print $s =~ /^(Tuesday.*?)^Friday/sm;' t1

    >>
    >>Thank you, it is a nice idea ( but for too much long files, perhaps ).
    >>

    >
    > "but for too much long files, perhaps"
    >
    > I would give this credibility if you can show some code that
    > guarantees there is a 'Friday'.


    True. My code behaves differently than the original if the Friday is
    missing. But maybe a range which doesn't end with Friday is malformed
    and should be omitted. Mauro didn't specify, but this is definitely
    something he would have to consider.

    I was assuming that "Tuesday" and "Friday" are just arbitrary begin and
    end markers and that lines don't have a natural order. But what if they
    have? Given the input:

    Monday
    Wednesday
    Thursday
    Friday
    Saturday
    Sunday

    should it print

    Wednesday
    Thursday

    ?

    Then neither the range operator nor the regexp will work (both rely on
    "Tuesday" being there) and you would need a different approach (like
    converting weekdays to numbers and then checking whether the number is
    in [2, 5)).

    hp
    Peter J. Holzer, Sep 25, 2011
    #18
  19. On 2011-09-20 13:31, Mauro <> wrote:
    > I had expressed that doubt ( about long files ) since, if I understand
    > correctly, that solution read the whole file in memory.


    Yes, it does. Whether that's a problem depends on how long the file is,
    how much memory you have and what you are doing with the file. Caveat
    emptor!

    hp
    Peter J. Holzer, Sep 25, 2011
    #19
  20. mauro papandrea

    Mauro Guest

    On 25/09/2011 8.42, Peter J. Holzer wrote:
    >
    > True. My code behaves differently than the original if the Friday is
    > missing. But maybe a range which doesn't end with Friday is malformed
    > and should be omitted. Mauro didn't specify, but this is definitely
    > something he would have to consider.
    >
    > I was assuming that "Tuesday" and "Friday" are just arbitrary begin and
    > end markers and that lines don't have a natural order. But what if they
    > have? Given the input:
    >
    > Monday
    > Wednesday
    > Thursday
    > Friday
    > Saturday
    > Sunday
    >
    > should it print
    >
    > Wednesday
    > Thursday
    >
    > ?
    >
    > Then neither the range operator nor the regexp will work (both rely on
    > "Tuesday" being there) and you would need a different approach (like
    > converting weekdays to numbers and then checking whether the number is
    > in [2, 5)).
    >
    > hp


    Your assumption is quite correct, those day name were merely markers.
    Perhaps I oversimplified too much.
    In my original problem, my file is divided in sections and each of them
    begins with a special line ( easily identifiable because no other line
    can be like that, that file is produced by a tool ).
    I need to read each section and apply a kind of filter whose action
    depends upon the type of section ( the marker line has 2 parts: one
    equal for every section, and this can be used to find sections, and a
    second with a kind of label, that can be used to understand which
    section it is ), some are to be discarded and others to be changed.
    So I though that a line range was good way to start if I could omit last
    line in the range ( so that it could be used for next section ) but I am
    afraid I did not chose the right example and I apologize for that.

    Regards

    Mauro
    Mauro, Sep 26, 2011
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    46
    Views:
    966
    Antoon Pardon
    Jul 25, 2006
  2. WuyaSea Operator
    Replies:
    48
    Views:
    1,462
    Ben Phillips
    Sep 24, 2007
  3. Lew
    Replies:
    0
    Views:
    403
  4. Lambda
    Replies:
    2
    Views:
    393
    James Kanze
    Jul 16, 2008
  5. it_says_BALLS_on_your forehead

    extract range of lines using range op bug?

    it_says_BALLS_on_your forehead, Mar 3, 2006, in forum: Perl Misc
    Replies:
    3
    Views:
    187
    it_says_BALLS_on_your forehead
    Mar 3, 2006
Loading...

Share This Page