Percentage sign causing awk problems

looks like awk gets confused when there's a % next to a number.

command im running:

awk -F" " '/phxnaz001b/ && /vol/ && NF { if (($NF >= 80) && ($NF < 83)) { print ; print ; w++ } else if ($NF >= 83) { print ; c++ } } END { printf("%d:OK %d:WARNING %d:CRITICAL\n", o, w, c) }' /tmp/test.log

contents of /tmp/test.log

phxnaz001b      /vol/NFS_nagios/       2148GB    190GB    1957GB          9%
phxnaz001b      /vol/RCC01PLM_COPY/       5734GB    4738GB    996GB          83%
phxnaz001b      /vol/RCC01PLM_COPY/       5734GB    4738GB    996GB          83%
phxnaz001b      /vol/PHX01PLM/       9146GB    7462GB    1683GB          82%
phxnaz001b      /vol/PHX01PLM/       9146GB    7462GB    1683GB          82%
phxnaz001b      /vol/nfs_datastore03/       593GB    55GB    538GB          9%
phxnaz001b      /vol/electricCommander/       3673GB    3193GB    479GB          87%
phxnaz001b      /vol/NFS_nagios/       2148GB    190GB    1957GB          9%
phxnaz001b      /vol/RCC01PLM_COPY/       5734GB    4738GB    996GB          83%
phxnaz001b      /vol/RCC01PLM_COPY/       5734GB    4738GB    996GB          83%

it looks like the awk is thinking 9% means 90%. which is not the case. how can i modify this awk command to accurate grab the right lines from the log?

Substitute $NF for $NF+0

---------- Post updated at 11:06 PM ---------- Previous update was at 10:18 PM ----------

If you do not mind, allow me to mention a few things about your snipet.

awk -F" " '/phxnaz001b/ && /vol/ && NF { if (($NF >= 80) && ($NF < 83)) { print ; print ; w++ } else if ($NF >= 83) { print ; c++ } } END { printf("%d:OK %d:WARNING %d:CRITICAL\n", o, w, c) }' /tmp/test.log

-F" " : The default is already white space, making this unnecessary, unless you want to exclude tabs which in this case it not relevant.
/phxnaz001b/ : Since this is the first field $1=="phxnaz001b" can be used instead to directly compare for the string, avoiding the regex lookup match, which is more expensive.
/vol/ : this will try to match in the whole record or $0, which is more expensive than pointing directly to the field number i.e. $2 ~ /\/^vol/ , also by using the anchor ^, it doesn't have to search the whole field nor will it match in the middle if found.
&& NF : Not necessary, it will always be true if any of the other expressions evaluate to true.
print ; print : Not clear why you are displaying the same line twice if the range is between 80 and 82 inclusive.
"%d:OK : Always 0 since you are not keeping tally of what falls outside the warning or critical level.

Changing those elements, the result would be something like:

awk '$1=="phxnaz001b" && $2 ~ /^\/vol/ {if($NF+0 >= 80 && $NF+0 < 83){print; w++} else if($NF+0 >= 83){ print; c++ } else {print; o++}} END {printf("%d:OK %d:WARNING %d:CRITICAL\n", o, w, c)}' test.log

or removing the individual prints:

awk '$1=="phxnaz001b" && $2 ~ /^\/vol/ {print; if($NF+0 >= 80 && $NF+0 < 83)w++; else if($NF+0 >= 83)c++; else o++} END { printf("%d:OK %d:WARNING %d:CRITICAL\n", o, w, c)}' test.log
1 Like

Awk doesn't take % as a number. It is considered as a string. Try this:

awk '{if ((substr($NF,1,length($NF)-1)+0)>80) print}' test.log

Here you convert $NF which is a percentage (string) to a number by extracting the number from it. substr function still gives you a string. To convert it to a decimal you add 0 to it.

1 Like

Adding a number to a string causes awk to use the characters at the start of that string that specify a numeric value (or zero if there isn't a leading number) to the number. Using substr() to strip off trailing non-digits isn't necessary.

printf '%s\n' 99.44% 1E2percent infinity nonumber | awk '{print $1+0}'

produces something like:

99.44
100
inf
0

(The string used to represent infinity in awk output varies from system to system (usually inf , infinity , Inf , or Infinity ), but any input string starting with a case-insensitive inf should be interpreted by awk to be an infinite value when it is being evaluated as a number. And, as shown by the string starting with 1E2 , awk also recognizes exponential numeric formats.)