5

I have the following text...

BIOS Information
Manufacturer               : Dell Inc.
Version                    : 2.5.2
Release Date               : 01/28/2015

Firmware Information
Name                       : iDRAC7
Version                    : 2.21.21 (Build 12)

Firmware Information
Name                       : Lifecycle Controller 2
Version                    : 2.21.21.21

... which is piped into the following awk statement...

awk '{ if ($1" "$2 == "BIOS Information") var=$1} END { print var }'

This will output 'BIOS' in this case. I want to look for 'BIOS Information' and then set the third field, two lines down, so in this case 'var' would equal '2.5.2'. Is there a way to do this with awk?

EDIT: I tried the following:

awk ' BEGIN {
FS="[ \t]*:[ \t]*";
}
NF==1 {
  sectname=$0;
}
NF==2 && $1 == "Version" && sectname="BIOS Information" {
  bios_version=$2;
}
END {
  print bios_version;
}'

Which gives me '2.21.21.21' with the above text. Can this be modified to give me the first 'Version" following "BIOS Information"?

user1601716
  • 1,893
  • 4
  • 24
  • 53

3 Answers3

4

Following script may be an overkill but it is robust in cases if you have multiple section names and/or order of fields is changed.

BEGIN {
  FS="[ \t]*:[ \t]*";
}
NF==1 {
  sectname=$0;
}  
NF==2 && $1 == "Version" && sectname=="BIOS Information" {
  bios_version=$2;
} 
END {
  print bios_version;
}

First, we set input field separator so that words are not separated into different fields. Next, we check whether current line is section name or a key-value pair. If it is section name, set sectname to section name. If it is a key-value pair and current section name is "BIOS Information" and key is "Version" then we set bios_version.

gudok
  • 4,029
  • 2
  • 20
  • 30
3

To answer the question as asked:

awk -v RS= '
/^BIOS Information\n/ {
   for(i=1;i<=NF;++i) { if ($i=="Version") { var=$(i+2); exit } }
}
END { print var }
' file
  • -v RS= puts awk in paragraph mode, so that each run of non-empty lines becomes a single record.

  • /^BIOS Information\n/ then only matches a record (paragraph) whose first line equals "BIOS Information".

  • Each paragraph is internally still split into fields by any run of whitespace (awk's default behavior), so the for loop loops over all fields until it finds literal Version, assigns the 2nd field after it to a variable (because : is parsed as a separate field) and exits, at which point the variable value is printed in the END block.

    • Note: A more robust and complete way to extract the version number can be found in the update below (the field-looping approach here could yield false positives and also only ever reports the first (whitespace-separated) token of the version field).

Update, based on requirements that emerged later:

To act on each paragraph's version number and create individual variables:

awk -v RS= '

  # Helper function that that returns the value of the specified field.
  function getFieldValue(name) {
    # Split the record into everything before and after "...\n<name>   : "   
    # and the following \n; the 2nd element of the array thus created
    # then contains the desired value.
    split($0, tokens, "^.*\n" name "[[:blank:]]+:[[:blank:]]+|\n")
    return tokens[2]
  }  

  /^BIOS Information\n/ {
     biosVer=getFieldValue("Version")
     print "BIOS version = " biosVer
  }

  /^Firmware Information\n/ {
    firmVer=getFieldValue("Version")
    print "Firmware version (" getFieldValue("Name") ") = " firmVer 
  }

' file

With the sample input, this yields:

BIOS version = 2.5.2
Firmware version (iDRAC7) = 2.21.21 (Build 12)
Firmware version (Lifecycle Controller 2) = 2.21.21.21
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • That works perfectly, expanding on the question. Since i'm not using if statements in this. How can i get the output of all three versions in the above text? as variables? – user1601716 Jun 03 '16 at 15:46
  • This works but I am unable to reference the variables unless i know where they fall. qudok's version is a bit more ungraceful but it lets me set individual variable names and reference them later. Thanks! – user1601716 Jun 03 '16 at 16:06
0

Given:

$ echo "$txt"
BIOS Information
Manufacturer               : Dell Inc.
Version                    : 2.5.2
Release Date               : 01/28/2015

Firmware Information
Name                       : iDRAC7
Version                    : 2.21.21 (Build 12)

Firmware Information
Name                       : Lifecycle Controller 2
Version                    : 2.21.21.21

You can do:

$ echo "$txt" | awk '/^BIOS Information/{f=1; printf($0)} /^Version/ && f{f=0; printf(":%s\n", $3)}'
BIOS Information:2.5.2
dawg
  • 98,345
  • 23
  • 131
  • 206