"open" range operator

R

RjY

Summary: The "flip-flop" sed/awk-style range operator includes its end
points. I would like to know if there's a way to make it not do that.

To illustrate[1], suppose I have a file like this:

blah
START
bleourgh
END
fleurgh

then feeding it into perl -ne 'print if /START/../END/;' gives

START
bleourgh
END

What I would like is a range operator suitable for shell one-liners that
does the same but is false on the endpoints rather than true, so that
the above example would not include the endpoints and so simply print
"bleourgh".

Is there a short idiom for this that I have simply missed? It seems not
to be too exotic a use-case. I tried using ... instead of .. but it had
no effect (obviously I misunderstood the difference)

[1] for the mathematically inclined: the range operator works more like
a closed interval; I would like it to work like an open one. :)
 
S

sln

Summary: The "flip-flop" sed/awk-style range operator includes its end
points. I would like to know if there's a way to make it not do that.

To illustrate[1], suppose I have a file like this:

blah
START
bleourgh
END
fleurgh

then feeding it into perl -ne 'print if /START/../END/;' gives

START
bleourgh
END

What I would like is a range operator suitable for shell one-liners that
does the same but is false on the endpoints rather than true, so that
the above example would not include the endpoints and so simply print
"bleourgh".

Is there a short idiom for this that I have simply missed? It seems not
to be too exotic a use-case. I tried using ... instead of .. but it had
no effect (obviously I misunderstood the difference)

[1] for the mathematically inclined: the range operator works more like
a closed interval; I would like it to work like an open one. :)

This probably works. Same principle to check the return sequence 'string'
in scalar context:

print if ((/START/../END/) =~ /^(?:1\d+|[2-9]\d*)$/);

-sln

-------------------
use strict;
use warnings;

while (<DATA>)
{
print if ((/START/../END/) =~ /^(?:1\d+|[2-9]\d*)$/);
}

__DATA__

blah

blah
START
bleourgh
END
fleurgh

START
1
2
3
4
5
/(^1|E0)$/
6
7
8
9
/ \d
0
1
2
3
4
5
6
7
8
9
0
bleourgh
before
END
fleurgh

END

then feeding it into perl -ne 'print if /START/.
1
2
hello
3
4
../END/;' gives


END

asdf

then feeding it into perl -ne 'print if /START/../END/;' gives


abdsfasdg
 
C

C.DeRykus

It is ugly, but you can examine the flip-flop's return value:

    print if /START/../END/ and (/START/../END/) !~ /(^1|E0)$/
or
    $ff = /START/../END/; print if $ff and $ff !~ /(^1|E0)$/

or perhaps the magic-challenged might prefer:

$ff = /START/../END/;
print if $ff>1 and $ff =~ /^\d+$/;
 
S

sln

What I would like is a range operator suitable for shell one-liners that
does the same but is false on the endpoints rather than true, so that
the above example would not include the endpoints and so simply print
"bleourgh".
This probably works. Same principle to check the return sequence 'string'
in scalar context:

print if ((/START/../END/) =~ /^(?:1\d+|[2-9]\d*)$/);

I guess you could extrapolate this to cover all possible ranges:

# Start - End
print if (/START/../END/);

# not Start - not End
print if ((/START/../END/) =~ /^(?:1\d+|[2-9]\d*)$/);

# Start - not End
print if ((/START/../END/) =~ /^(?:[1-9]\d*)$/);

# not Start - End
print if ((/START/../END/) =~ /^(?:1\d+|[2-9]\d*)(?:E0)?$/);

-sln
 
R

RjY

Tad McClellan posted:
It is ugly, but you can examine the flip-flop's return value:

print if /START/../END/ and (/START/../END/) !~ /(^1|E0)$/
or
$ff = /START/../END/; print if $ff and $ff !~ /(^1|E0)$/

Thank you, this will do fine :)

Thanks to all who answered.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,164
Messages
2,570,898
Members
47,439
Latest member
shasuze

Latest Threads

Top