Hi again Me,
further to my thanks, I've had a look at your suggestions. As it
turns out it's your last (less obfuscated) solution that I needed. I've
attached a working example.
However, it was the more obfuscated ones I thought I understood better, but
when I try the second one (to match all) I don't get the same result as when
I use the equivalent (?) longer one.
I've commented the code with my understanding of what's happening for the
more verbose solution, but I must confess I thought the shorter version
would work too. I've tried it and included the output. There's no
difference whether I add the ';' after the { or not - but I didn't think it
was necessary 8-).
Am I missing something in your compact suggestions?
Here's my artificial, but working, code:-
=======start quote==========
#!/usr/bin/perl -w
use strict;
use diagnostics;
use warnings;
my @printLine = [];
my @headingLine = ("Start ",
"Started ",
"Stop ",
"Stopped \n" );
my @emptyLine = ("---------- ",
"---------- ",
"---------- ",
"----------\n" );
while (<DATA>) {
my ($state, $time) = split;
if ($state == -1) {
print @headingLine;
@printLine = @emptyLine;
print @printLine;
next;
}
#
# $state comes in as 0, 1, 2 or 3 - if each element from $state's value
to the last
# matches an "empty" element, then it's ok to plug $time in, else we
need to print
# as much as we have on the line, "empty" it, and plug the new value in
the correct slot
#
# if($state..3 == grep{/^----/} @printLine[$state..3]) {
my $match = 1; # set to true.
for ($state..3) { # see if each slot to the
right of where this
$match &&= $printLine[$_] =~ /^-----/; # goes is "empty" ie
matches /^----/
} # if they're all empty, new
time goes
if ($match) {
$printLine[$state] = "$time "; # where $state says to.
} else { # otherwise print the line as
it is, clear it
print @printLine, "\n"; # out and put the new time
where it belongs
@printLine = @emptyLine; # to be printed when
required.
$printLine[$state] = "$time ";
}
}
print @printLine, "\n"; # yup, without some smarts,
this may print all ---s
__END__
-1
0 23:40:47.9
1 12:13:22.5
2 18:36:11.0
3 06:02:26.2
0 00:45:39.7
2 03:18:30.0
3 05:58:41.3
0 05:21:55.7
1 15:34:01.8
2 10:43:28.5
3 15:15:12.4
2 04:34:15.1
3 09:52:56.5
0 00:56:23.0
======= end quote =======
RESULTS
>>> Correct
D:\perl\scripts\DAMS\modules>rangechk.plx
Start Started Stop Stopped
---------- ---------- ---------- ----------
23:40:47.9 12:13:22.5 18:36:11.0 06:02:26.2
00:45:39.7 ---------- 03:18:30.0 05:58:41.3
05:21:55.7 15:34:01.8 10:43:28.5 15:15:12.4
---------- ---------- 04:34:15.1 09:52:56.5
00:56:23.0 ---------- ---------- ----------
>>> Not so correct
D:\perl\scripts\DAMS\modules>rangech2.plx
Start Started Stop Stopped
---------- ---------- ---------- ----------
---------- ---------- ---------- ----------
00:56:23.0 15:34:01.8 04:34:15.1 09:52:56.5
Once again thanks for taking the time.
Cheers
Murray Webster
-----Original Message-----
From: Me [mailto:[EMAIL PROTECTED]]
Sent: Wednesday, 4 July 2001 16:12
To: Webster, Murray; [EMAIL PROTECTED]
Subject: Re: Match range of array elements?
> if ($printLine[$state..3] =~ /^----/)
1. The syntax $foo[....] signifies a single element of array @foo.
The ..... bit is in scalar context and should evaluate to a *single*
*numeric* value. Hence the complaint:
Argument "" isn't numeric in array element
2. When you use a variable that isn't defined, and you have
warnings switched on, perl will complain. For some lines of
your TEST file, $state ends up not defined, hence:
Use of uninitialized value in pattern match (m//)
The line number for the specific lines is given in the error message.
To make matters worse:
3. When you use the X..Y syntax in a scalar context, the ..
operator is the bistable (flipflop) operator, not the range
operator.
4. The =~ operator expects a single value on the left side.
You clearly ain't doing what you want to do.
I don't know what happens earlier in your script (and given
the errors above, I ain't too confident you've gotten it right),
but to match against a range of array elements, how you
might want to try:
if (grep { /^---/ } @printLine[$state..3]) {;
to match any, or
if ($state..3 == grep { /^---/ } @printLine[$state..3]) {;
to match all. You should add an assert that $state is (or
evaluates to) an integer between 0 and 3. And both of
these are somewhat obfuscated coding. Perhaps:
# to match any
my $match = 0;
for ($state..3) {
$match ||= $printLine[$_] =~ /^---/
}
if ($match) {
or
# to match all
my $match = 1;
for ($state..3) {
$match &&= $printLine[$_] =~ /^---/
}
if ($match) {
would be better, though note that the latter indicates
you have matched all if $state isn't in the range 0-3.
hth.