deep
deep

Reputation: 716

Perforce commands Regular Expressions

I am having the lines of a perforce command execution as follows:

2806  I deep  sd_bordeaux 117:02:40 IDLE none
2807  I deep  sd_bordeaux 17:02:40  IDLE none
2808  I deep  sd_coddeaux 117:02:40 IDLE all
2809  I rahul sd_coddeaux 117:02:40 IDLE all

I have written the following code to run the command to get the above list in $command and store it in a array @lines and use regex to get the specified conditions. But I am not getting the desired results.

my $command = qx |p4 monitor show -ale|;
my $kill_id;
my @lines = split("\n", $command);
for my $line (@lines){
    next if not $line =~ /(\d+)\s+/;
    my $id = $1;
    if ($line =~ /sd_bordeaux\s+(\d+):\d+:\d+\s+/ and $line =~ /IDLE\s+none$/){
        my $hours = $1;
        print "$hours";
        print "\n";
    }

}

I am getting an error

Use of uninitialized value $hours in string at ./p4.pl

I am interested in getting the numbers "2806" and "2807" as $id and the first digits "117" & "17" as $hours.

Please can some help me where I am going wrong. Thank you.

Upvotes: 0

Views: 205

Answers (2)

Garry
Garry

Reputation: 109

With data as organised as that, why use a regex at all?

for my $line (@lines) {
  my @elems = split /\s+/, $line;
  next unless $elems[3] eq "sd_bordeaux";
  next unless $elems[-2] eq "IDLE";
  next unless $elems[-1] eq "none";
  print "$elems[0]\n";
}

Out of interest even if your regex had responded with something, it wouldn't have given you the 280x you're expecting; it would have given you e.g. the 117 part from 117:02:40

If for some reason it's got to be a regex, you could do it with ..

if $line =~ /^(\d+)\s+.s*sd_bordeaux\s+(\d+).*IDLE\snone$/ {
  my $id = $1;
  my $hours = $2;

... that should at least return the number you're expecting.

Upvotes: 1

ikegami
ikegami

Reputation: 385657

$1 contains what was matched by the first capture of the most recent successful regex match.

When you get the error, the most recent successful match was against /IDLE\s+none$/ which contains no captures.

The following would be equivalent:

if ($line =~ /sd_bordeaux\s+(\d+):\d+:\d+\s+/) {
    my $hours = $1;
    if ($line =~ /IDLE\s+none$/) {
        print "$hours\n";
    }
}

But it looks like all you need is the following:

if ($line =~ /sd_bordeaux\s+(\d+):\d+:\d+\s+IDLE\s+none$/) {
    my $hours = $1;
    print "$hours\n";
}

That explains the problem and how to solve it, but Garry provides an alternative approach that's more readable.

Upvotes: 2

Related Questions