The flip flop operator isn't that hard to use. Not in it's
simple form anyway. ;) It's ideal spot is for soaking up
data from between two identifiable strings. eg
while(<>)
{
if(/string1/ .. /string2/)
{
print;
}
}
This will print:
string1
.....
string2
Note that string1 and string2 remain in the output.
shift and pop can help you get rid of them if you don't like
them. (Or use splice).
There are far nicer solutions to this problem than using
a flip-flop operator, however for demonstrational purposes,
this is how I'd solve this using the flip flop.
Note that I've added in a third tag to make it more
interesting.
#!/usr/bin/perl -w
use strict;
my (@desc, @data, @new);
while(<>)
{
chomp;
if(($_ eq "Description:") .. ($_ eq "Data:"))
{
push @desc, $_;
next unless $_ eq "Data:";
}
# if you have another tag
if(($_ eq "Data:") .. ($_ eq "NewTag:"))
{
push @data, $_;
next unless $_ eq "NewTag:";
}
# and so on until the last tag
push @new, $_;
}
shift @desc; # get rid of "Description:" from front.
pop @desc if @data; # get rid of "Data:" as last element.
shift @data; # get rid of "Data:" from front.
pop @data if @new; # get rid of "NewTag:" as last element.
shift @new; # get rid of "NewTag:" from front.
print "desc: @desc\n";
print "data: @data\n";
print "new: @new\n";
The reason this works (for those people who didn't do or
hated electrical or computer engineering) is that the flip
flop operator flips to true once the first condition is fulfilled
and stays true until the second condition is true where it
then flops to false.
So you can have as much gunk above "Description:" as you like
and the .. operator will not change. Once "Description:" is
seen the .. operator becomes true and the if condition is
therefore also true. Once "Data:" is seen the .. operator
becomes false (but after the if condition has evaluated to
true). If "Description:" should be seen again, then the
.. operator would once again flip to true and the if condition
would be active.
There are some interesting problems that come up with using
the flip flop operator. For starters, if you had another
condition in this list:
if(($_ eq "NewTag:") .. ($_ eq "Somethingelse:"))
{
...
}
then it would be possible for two conditions to be active
at one time even though only the highest on the list would
get any data. This could occur if your file looked like this:
NewTag: # sets the third flip flop to true
...
Description: # sets the first flip flop to true
...
Somethingelse: # is a data line for Description
....
Data: # now the first flip flop will be
.... # false and the second true
NewTag: # sets second flip flop to false
.....
..... # these get given to the third
..... # option finally.
This of course means that if your data file has missing
sets, wierd things will happen. In fact, if a necessary
condition does not occur you'll either get too much data
or not enough. For example processing a log file with something
like:
if(/$date1/../$date2/)
{
}
should never even be attempted unless you are 300% sure that
both $data1 and $date2 will be in that log file and every
single other log file you might ever deal with.
I got bitten by that one.
Jacinta |