Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Greedy flip flop operator?

by chengchl (Acolyte)
on Apr 26, 2018 at 06:46 UTC ( [id://1213573]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Perl Monks,

I have a question about flip flop operator ( /pattern/ .. /pattern/ ) and hope for your instructions/thoughts.

Suppose I have a text file like this :

start text

+ 123

+ 456

+ 789

some other text not starting with +

I would like to extract from "start text" to the one line before "some other text not starting with +". That is to say, in this example, to extract the first four lines.

I wrote a script like this -

#!/usr/bin/perl use strict; use warnings; my $file = "file_name_to_the_txt"; open(my $fh,'<',$file) or die "Warnings: $!\n"; while (<$fh>) { print if (/^start/ .. /^\+/); } close ($fh);
===

but it only generates the first two lines. Is there a way to have a greedy flip flop operator? thanks in advance.

Replies are listed 'Best First'.
Re: Greedy flip flop operator?
by choroba (Cardinal) on Apr 26, 2018 at 08:44 UTC
    Using three dots and negating the condition works, but you have to omit the last line, which is easy if you capture the value returned by the flipflop and check it for E:
    #!/usr/bin/perl use warnings; use strict; while (<DATA>) { if (my $flip = /^start/ ... /^[^+]/) { print unless $flip =~ /E/; } } __DATA__ start text + 123 + 456 + 789 some other text not starting with +

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: Greedy flip flop operator?
by hippo (Bishop) on Apr 26, 2018 at 08:09 UTC
    Is there a way to have a greedy flip flop operator?

    Not that I am aware of. However there are lots of ways to achieve the same effect. Here's one:

    use strict; use warnings; use Test::More tests => 1; my $want = <<EOT; start text + 123 + 456 + 789 EOT my $out; while (<DATA>) { last unless (/^(start|\+)/); $out .= $_ } is ($out, $want); __DATA__ start text + 123 + 456 + 789 some other text not starting with +

    If your actual data is different then you might have to try another approach but I think this should be fairly efficient.

Re: Greedy flip flop operator?
by Discipulus (Canon) on Apr 26, 2018 at 07:14 UTC
    Hello chengchl,

    You need this:  print if (/^start/ .. /^\[^\+]/); # EDIT: /^\[^\+]/ is wrong!

    Infact your version says: print between start and (the first) + included , while mine prints between start and a not + included. ie it will print also the first new line without a leading +

    The flip flop operator is already greedy: it is true between two patterns, included. In you case perhaps it's better something else: have a switch that signal if start was found and if so just print out strings starting with a + sign.

    PS see also my library links

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
      > /^\[^\+]/

      Shouldn't it rather be  /^[^+]/ ?

      I'd also test for following \w+ to avoid whitespace confusion.

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Wikisyntax for the Monastery

        /^[^+]/ will end at the first empty line (if they really are there as shown).. anyway you are right: I must not post before coffe

        L*

        There are no rules, there are no thumbs..
        Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
        Hi Rolf, It seems it will only print the first line... When i execute the code as you instructed.
      Thanks L. I think we should use ... instead of .. for the flip flop operator. Thanks again!
Re: Greedy flip flop operator?
by poj (Abbot) on Apr 26, 2018 at 07:19 UTC

    some other text not starting with +

      print if (/^start/ .. /^[^+]/ && !/^start/);

    poj
      Hi Poj, Thanks but this will print the whole text... I think...
Re: Greedy flip flop operator?
by tybalt89 (Monsignor) on Apr 26, 2018 at 20:50 UTC
    #!/usr/bin/perl # http://perlmonks.org/?node_id=1213573 use strict; use warnings; #print join('', <DATA>) =~ /^start.*\n(?:\+.*\n)*/gm; # my preference +:) while(<DATA>) { /^start/ .. /^(?!start|\+)/ and /^(start|\+)/ and print; } __DATA__ ignore this line :) start text + 123 + 456 + 789 some other text not starting with + another test case start text + foo + bar start text + one + two + three also ignore this line

    Outputs:

    start text + 123 + 456 + 789 start text + foo + bar start text + one + two + three
Re: Greedy flip flop operator?
by RonW (Parson) on Apr 26, 2018 at 19:56 UTC
Re: Greedy flip flop operator?
by Anonymous Monk on Apr 26, 2018 at 14:24 UTC
    I do it like this:

    while (my $line = <$fh>) { chomp $line; ($line =~ /start text|^\+/) && print "$line\n"; }

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (4)
As of 2024-04-24 02:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found