1

I have this output from a drive diag command.

Slot Number        : 0   
Drive's position   : DiskGroup 0  
Media Error        : 0   
Other Error        : 0   
Predictive Failure : 0   
Raw Size           : 447.130 GB [0x37e436b0 Sectors]
Firmware state     : Online, Spun Up 
Inquiry Data       : PHYM813201FL480BGNSSDSC2KG480G7R SCV1DL58  
Foreign State      : None   
Media Type         : Solid State Device 
Temperature        : 20C (68.00 F) 
S.M.A.R.T alert    : No   

Slot Number        : 1   
Drive's position   : DiskGroup 0  
Media Error        : 0   
Other Error        : 0   
Predictive Failure : 0   
Raw Size           : 447.130 GB [0x37e436b0 Sectors]
Firmware state     : Online, Spun Up 
Inquiry Data       : PHYM81320058480BGNSSDSC2KG480G7R SCV1DL58  
Foreign State      : None   
Media Type         : Solid State Device 
Temperature        : 21C (69.80 F) 
S.M.A.R.T alert    : No   

Slot Number        : 2   
Drive's position   : DiskGroup 1  
Media Error        : 0   
Other Error        : 0   
Predictive Failure : 0   
Raw Size           : 1.090 TB [0x8bba0cb0 Sectors]
Firmware state     : Online, Spun Up 
Inquiry Data       : SEAGATE ST1200MM0099 ST31WFK0VEBK 
Foreign State      : None   
Media Type         : Hard Disk Device 
Temperature        : 22C (71.60 F) 
S.M.A.R.T alert    : No   

Slot Number        : 3   
Drive's position   : DiskGroup 1  
Media Error        : 0   
Other Error        : 0   
Predictive Failure : 0   
Raw Size           : 1.090 TB [0x8bba0cb0 Sectors]
Firmware state     : Online, Spun Up 
Inquiry Data       : SEAGATE ST1200MM0099 ST31WFK0T07T 
Foreign State      : None   
Media Type         : Hard Disk Device 
Temperature        : 22C (71.60 F) 
S.M.A.R.T alert    : No   

Slot Number        : 4   
Drive's position   : DiskGroup 1  
Media Error        : 0   
Other Error        : 0   
Predictive Failure : 0   
Raw Size           : 1.090 TB [0x8bba0cb0 Sectors]
Firmware state     : Online, Spun Up 
Inquiry Data       : SEAGATE ST1200MM0099 ST31WFK0VAJK 
Foreign State      : None   
Media Type         : Hard Disk Device 
Temperature        : 22C (71.60 F) 
S.M.A.R.T alert    : No   

Slot Number        : 5   
Drive's position   : DiskGroup 1  
Media Error        : 0   
Other Error        : 0   
Predictive Failure : 0   
Raw Size           : 1.090 TB [0x8bba0cb0 Sectors]
Firmware state     : Online, Spun Up 
Inquiry Data       : SEAGATE ST1200MM0099 ST31WFK0SYPC 
Foreign State      : None   
Media Type         : Hard Disk Device 
Temperature        : 22C (71.60 F) 
S.M.A.R.T alert    : No   

Slot Number        : 6   
Drive's position   : DiskGroup 1  
Media Error        : 0   
Other Error        : 0   
Predictive Failure : 0   
Raw Size           : 1.090 TB [0x8bba0cb0 Sectors]
Firmware state     : Online, Spun Up 
Inquiry Data       : SEAGATE ST1200MM0099 ST31WFK0MVN2 
Foreign State      : None   
Media Type         : Hard Disk Device 
Temperature        : 22C (71.60 F) 
S.M.A.R.T alert    : No   

Slot Number        : 7   
Drive's position   : DiskGroup 1  
Media Error        : 0   
Other Error        : 0   
Predictive Failure : 0   
Raw Size           : 1.090 TB [0x8bba0cb0 Sectors]
Firmware state     : Online, Spun Up 
Inquiry Data       : SEAGATE ST1200MM0099 ST31WFK0SZ2L 
Foreign State      : None   
Media Type         : Hard Disk Device 
Temperature        : 22C (71.60 F) 
S.M.A.R.T alert    : No 

And I would like to only make changes on the 3,4,5,7,9 and 12th line of each drive after the ":" sign. Those results are the standards but I want to add some color if it says something different. For example:

Slot Number        : 7   
Drive's position   : DiskGroup 1  
Media Error        : 4  (I want the whole line in red)
Other Error        : 3  (I want the whole line in red)
Predictive Failure : 1  (I want the whole line in red)
Raw Size           : 1.090 TB [0x8bba0cb0 Sectors]
Firmware state     : Failed. (I want the whole line in red)
Inquiry Data       : SEAGATE ST1200MM0099 ST31WFK0SZ2L 
Foreign State      : Unconfigured  (I want the whole line in red)
Media Type         : Hard Disk Device 
Temperature        : 22C (71.60 F) 
S.M.A.R.T alert    : Yes  (I want the whole line in red)

I would like to make those changes for every drive, the drive quantity is variable, sometimes is more sometimes is less.

I already tried this but is not working.

awk -F ':' '$1~/^(Media Error|Other Error|Predictive Failure)$/ && $2 > 0 {print "\033[31m" $0 "\e[0m"; next} 1'
0

2 Answers 2

4

You were pretty close to getting it right. I will respond with Bash and Awk. What you seem to be asking for is:

$ awk '/(Media Error|Other Error|Predictive Failure|Firmware state|Foreign State|S\.M\.A\.R\.T alert)[[:blank:]]+:/{print "\033[31m" $0"\033[0m"; next} 1' < <(your_drive_diag_command)

Aspects of what you did try before posting deserve a few comments:

  • -F ':'
    Specifying a field separator different from the default blank space is only useful if you actually need to act on record's fields. It does not seem to be the case here.

  • $1 ~ /^(Media Error|Other Error|Predictive Failure)$/ ...
    You test the first field ($1 before the specified field separator :) for 3 different possibilities in terms of string value with the | (OR) Boolean. That's fine in principle, but in this case you might get away with simply testing for the presence of the strings anywhere in the whole record ($0) just making sure that you complete the sought string regex with \s+: for Gawk or [[:blank:]]+: for any Awk flavor. This adds a number of Spaces/Tabs >= 1 before a colon : to each sought string. In other words you probably can do away with testing $1 with a regex that involves ^ and $.

  • I aligned your color coding for consistency so \e becomes \033.

Edit 1:
Following @JosueBaquerizo's additional specifications, the logic changes to include conditional statements on both $1and $2:

$ awk -F ' *: *' '
      ($1 ~ /Media Error|Other Error|Predictive Failure/ && $2 > 0 ||
       $1 ~ /Firmware state/ && $2 ~ "Failed" ||
       $1 ~ /Foreign State/ && $2 ~ "Unconfigured" || 
       $1 ~ /S\.M\.A\.R\.T alert/ && $2 ~ "Yes") {print "\033[31m" $0"\033[0m"; next} 1' < <(your_drive_diag_command)
4
  • 1
    @Cbhihe Thank you for helping, I got the lines that you specified to get a red color, BUT, I only want them to be red if the results (what comes after the " : ") changes from the standard. For example: S.M.A.R.T. alert : Yes, or , Media Error : 23. Apr 10, 2022 at 19:40
  • Thank you for your help! It works perfect! I have one last question, in the part $1 ~ /Media Error|Other Error|Predictive Failure/ && $2 > 0 {print "\033[31m" $0"\033[0m"; next} , where $2 is what comes after the ':' sign, how can I do if I want to just specify the first 2 characters? Apr 11, 2022 at 19:46
  • IT would be for a different scenario. For example i have this output: ch0: 0 A1 ch1: 23 A2 I still want to apply the same idea, but if you notice, after the ':' sign, I have more output than just the number of errors, but A1 and A2 thats the location of the device so that doesnt matter. I want to apply the same logic, when its > 0 print all line in red. @Cbhihe Apr 13, 2022 at 1:41
  • @JosueBaquerizo: This is a different question, Josue. This forum expects new questions to be asked separately so a thread constituted by an original post (OP) and its answer(s) remains unpolluted. If you ask a new question and tag it properly, I and many others will be sure to see it and to answer. ;-)
    – Cbhihe
    Apr 13, 2022 at 7:29
2

Using any awk:

$ awk -F '[[:space:]]*:[[:space:]]*' '
    BEGIN {
        tag2val["Media Error"]          = 0
        tag2val["Other Error"]          = 0
        tag2val["Predictive Failure"]   = 0
        tag2val["Firmware state"]       = "Online, Spun Up"
        tag2val["Foreign State"]        = "None"
        tag2val["S.M.A.R.T alert"]      = "No"
    }
    {
        tag = $1
        val = $2
        sub(/^[[:space:]]+/,"",tag)
        sub(/[[:space:]]+$/,"",val)
    }
    (tag in tag2val) && (val != tag2val[tag]) {
        $0 = "\033[31m" $0 "\033[0m"
    }
    { print }
' file

You just have to include the blanks around the : so the first thing in $2 isn't a blank and strip any trailing spaces (such as you have in your input) from the end of the line. I also tidied up your end-of-color escape sequence and set $0 instead of printing there so you don't need a next and output coming from 2 different places.

2
  • Thank you for your reply! It works perfect now! I like this method better because if there is an unexpected output this will catch it. Thanks! Apr 18, 2022 at 2:52
  • You're welcome. If you plan to use this answer then you should accept it, see unix.stackexchange.com/questions/tagged/awk
    – Ed Morton
    Apr 18, 2022 at 11:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .