Get a specific word using awk

8,101

Solution 1

You don't need to read file line-by-line using bash. Awk does that already. For instance, you can print broken entries using this code

awk '$2!="OK"{print $0}'  check.log

You can also just print the table name and use that command to create an array, then act upon those:

array=( $(awk '$2!="OK"{printf "%s ",$1 }'  check.log) )

Note the space next to %s, that's important.

You mentioned also, that error can be multiline, just like for table8. We probably want to avoid messing with that. So we may add a check also for field 1 to contain a word table.

$> array=( $(awk '$1~/table/ && $2!="OK"{printf "%s ",$1 }'  check.log) )      
$> echo ${array[@]}                                                            
table2 table5 table7 table8
$> echo ${array[0]}                                                            
table2

Solution 2

Since awk's default behaviour is to print the full line when a True condition happens, you can say something as simple as this:

awk '$NF != "OK"' file

Which returns the following for your given input:

table2                 Some error here
table5                 Another error
table7                 Broken
table8                 A very long error which take a 2 lines
of multiple errors

Explanation

  • NF stands for number of fields, so $NF stands for field number NF. That is, the last field on every line.
  • Saying $NF != "OK" we are checking if the last field on the line is "OK" or not. If it is not, the condition is true and the line gets printed automatically.
Share:
8,101

Related videos on Youtube

Abu Rayane
Author by

Abu Rayane

Updated on September 18, 2022

Comments

  • Abu Rayane
    Abu Rayane over 1 year

    I am coding a script to check mysql databases using bash script, I would like to check if the status of a table is not 'OK', will return the table name and do some more actions:

    check.log

    table1                 OK
    table2                 Some error here
    table3                 OK
    table4                 OK
    table5                 Another error
    table6                 OK
    table7                 Broken
    table8                 A very long error which take a 2 lines
    of multiple errors
    

    check.sh

    # check and repair tables
    mysqlcheck -u $hostUser -p$hostPasswd --all-databases --check --auto-repair >> check.log
    
    # grep tables status, should return OK
    cat check.log | grep 'OK' | awk '{print $2}'| while read status; do
    
    # if any table does not contain OK
    if [ "$status" != "OK" ]
    then
    ##### HERE WHERE I am stuck
    #### It loops and return all the table
    
    # grep to get the table name
    cat check.log | grep 'OK' | awk '{print $1}'| while read table; do
    echo $tblName' is BROKEN'
    done
    else
    echo $tblName' is FINE'
    fi
    
    done
    
    // here I need to mail the tables that have problems in one single mail
    

    Looking for an output like:

    tableName: error
    tableName: error
    
    table2: Some error here
    table5: Another error
    and so on
    

    These lines will be an output into a log file (result.txt)

    Thanks for your support

    • Jacob Vlijm
      Jacob Vlijm about 8 years
      Do you have a specific reason to use awk?
    • Abu Rayane
      Abu Rayane about 8 years
      Well if there is a better method, why not
  • Abu Rayane
    Abu Rayane about 8 years
    Oh yeah, awesome, how can I print the content of the array?
  • Abu Rayane
    Abu Rayane about 8 years
    Tables can have different names, I am looking to get a result like the above mentioned in my edited question
  • Sergiy Kolodyazhnyy
    Sergiy Kolodyazhnyy about 8 years
    @AbuRayane that's it ? You just want lines like tableX Error#25 ?
  • Sergiy Kolodyazhnyy
    Sergiy Kolodyazhnyy about 8 years
    In that case , awk '$2!="OK"{print $0}' check.log, my first code is what you want.
  • Abu Rayane
    Abu Rayane about 8 years
    I found that with this behaviour the array has only one parameter, and I could not do a loop, for example for field in array do...
  • Abu Rayane
    Abu Rayane about 8 years
    It is a good toot, I am looking to print the result per rows, as I edited in my question above, see the part "Looking for an output like:"
  • Abu Rayane
    Abu Rayane about 8 years
    mysqlcheck will return some errors in a very long line (so to prevent that, I am saying it CAN be multi line) to not have any error in the code
  • fedorqui
    fedorqui about 8 years
    @AbuRayane you should edit your question to show what exact output you want. Currently it is unclear.
  • Abu Rayane
    Abu Rayane about 8 years
    The solutions that you give and Serg as well gave me, are correct, it is only a matter of a display, I need to display the result line by line, i.e: table2: error then a new line table3: error another new line table5: error and so on
  • fedorqui
    fedorqui about 8 years
    @AbuRayane so instead of the full error you just want to display the string "error"?
  • Abu Rayane
    Abu Rayane about 8 years
    No, the full error, but line by line display as mentioned above
  • fedorqui
    fedorqui about 8 years
    @AbuRayane this is a bit tiring. Edit your original question indicating what exact output you want. You are currently saying either tableName: error and table2: Some error here. This is very unclear.