Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

awk set variable to line after if statement match

Tags:

awk

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"?

like image 884
user1601716 Avatar asked Jun 03 '16 14:06

user1601716


2 Answers

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.

like image 81
gudok Avatar answered Nov 12 '22 03:11

gudok


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
like image 38
mklement0 Avatar answered Nov 12 '22 01:11

mklement0