2

I'm having a bit of trouble pulling certain values from a variable in my Perl script on an Ubuntu 12.04 box.

I looked over this page: How to extract string following a pattern

And this is sort of what I want to do. I need to extract a string value after a certain pattern. Here's the code I have thus far:

foreach $HDD (@sds)
{
    $hdStat = `hdparm -i $HDD | grep -Po 'Model=\K.*?(?=,)'`;
    $sdModel{$HDD} = $hdStat;
    $hdStat = `hdparm -i $HDD | grep -Po 'SerialNo=\K.*?(?=")'`;
    $sdSerial{$HDD} = $hdStat;
}
foreach $HDD (keys %sdModel)
{
    print $sdModel{$HDD};
}
foreach $HDD (keys, %sdSerial)
{
    print $sdSerial{$HDD};
}

It will return the Model string just fine, but it won't return the SerialNo string. The code doesn't have to be with grep; I just modified the code from the link above. And seeing as how I am terrible with regex, I'm probably missing something basic here.

Btw, the purpose of this code is to look through the /dev folder to find any disk drives, and if it does, sets it into an array, where the above script will then get it's Model # and Serial #. Also, if anyone sees a better way to do what I'm doing, I am very open to suggestions. I am still very new to Perl (only been with it about a week so far).

Community
  • 1
  • 1
Arkevius
  • 59
  • 1
  • 7
  • 2
    Perhaps you should show your input and expected output instead. It's like the difference between asking how to find the way from New York to Boston, and asking directions how to drive a car. – TLP Oct 13 '12 at 18:17
  • @TLP Sorry, I'm new to the forums as much as I am new to Perl. My input would be an element from the array sds, which in this case would be ' /dev/sda '. The output should be the model number and serial number of that drive, which in this case would be ' ST380011A ' and ' 5JVJ2BBA '. However, the serial number was not coming back, and I'm guessing it's because of the delimiter afterwards. Just a guess though. – Arkevius Oct 13 '12 at 19:04

2 Answers2

1

First, you don't print $sdSerial.

Second, you could save some external calls and simplify your regexp with:

foreach my $HDD (@sds) {
    my @hdparm = `hdparm -i $HDD`;
    foreach my $ln (@hdparm) {
        if (my($model, $serial) = ($ln =~ m/Model=(.+?),.+?,\s*SerialNo=(.+)/)) {
            $sdModel{$HDD} = $model;
            $sdSerial{$HDD} = $serial;
        }
    }
}

The above can be simplified to:

foreach my $HDD (@sds) {
    my $hdparm = `hdparm -i $HDD`;
    if (my($model, $serial) = ($hdparm =~ m/Model=(.+?),.+?,\s*SerialNo=(.+)/)) {
        $sdModel{$HDD} = $model;
        $sdSerial{$HDD} = $serial;
    }
}
ikegami
  • 367,544
  • 15
  • 269
  • 518
Olaf Dietsche
  • 72,253
  • 8
  • 102
  • 198
  • I must have forgotten to add that print in, thanks for catching that. I had it in my original code though, so that wasn't the problem. I tried your code and it works! Saves me a bit of room too. Thank you for the help! – Arkevius Oct 13 '12 at 19:00
0

In order to extract serial number try this regexp:

$hdStat = `hdparm -i $HDD | grep -Po 'SerialNo=\K.*?'`;
Massimo
  • 75
  • 10
  • That doesn't seem to be working for me. I typed that in straight on the CLI of my Ubuntu box but nothing was returned (I cut out the variable of course and just left "hdparm ...." – Arkevius Oct 13 '12 at 18:55