0

when I want to check if a returned value is integer or not I use this in bash script:

  if [ -z "$value" ]
    then
    echo 0
    else
    echo $value
  fi

I was trying to use z option in awk with if. for example i have this line:

PRIMARY SECONDARY CONNECTED 350 800  

I tried using this:

/bin/awk '{if( -z $1){print "0"}else{print $1}}' script  

no matter i replace $1 with $2 or $3 or $4 or $5 it always return 0. am I using awk in a wrong way?

3 Answers3

2

-z in shell will not tell you "if a value is integer or not", but whether its length is > 0.

You can do the same in awk with length -- if(length($1)) ...

If you want to check if a variable or field is a number or not in awk, you could do this:

 if($1+0 || $1~/^[+-]?0/) ...

Your if(-z $1) expression will simply negate the unset variable z, which will yield 0, and then append the 0 to the $1 field, creating a non-empty string which will be always considered TRUE, even if $1 was the empty string "" or the number 0.

  • would you please explain what is ($1+0 || $1~/^0/) doing? – BlackCrystal Feb 05 '19 at 09:34
  • $1+0 checks if the numeric value of $1 is non-zero (which will be if $1 is already a non-zero number or is a string which starts with a non-zero number), and $1~/^0/ checks if it's the number 0 or a string starting with 0 (not "foo", or "", which will also evaluate to 0 when converted to a number) –  Feb 05 '19 at 09:44
  • If you're only interested in non-negative integers, you can get away with this $1~/^[0-9]/. For numbers in general, you'll have to implement the whole of strtod() in slow awk if you don't like my hack. –  Feb 05 '19 at 09:50
  • One idiom in awk is to test $1+0 == $1, that is to force the value to a number and see if it compares equal to the original. (Strings get turned to 0 in the process, and that doesn't compare equal to the original string.) This accepts anything awk thinks is a number, like 123.34e5, or -0. – ilkkachu Feb 05 '19 at 10:10
  • @ilkkachu that won't do. not even for your example: echo | awk '{$1="123.34e5"; print $1, $1+0, $1+0 == $1}'. You shouldn't try with fields, because awk not only splits a line with IFS, it also turns into numbers the fields which look like numbers (pass the strtod-test). echo 0 | awk '{print $1 ? "yes" : "no"; $1="0"; print $1 ? "yes" : "no"}' –  Feb 05 '19 at 14:43
  • @pizdelect, mm, it works for me in echo 123.34e5 | awk '{ print $1, $1+0, $1+0 == $1 }'. But perhaps you're right, perhaps it does some autodetecting. – ilkkachu Feb 05 '19 at 17:16
  • It seems you still don't believe me, despite the evidence. That's documented behavior (in mawk's manpage and in the POSIX standard -- "Each array element shall have a string value when created and, if appropriate, the array element shall be considered a numeric string" -- though not in gawk's, even if gawk is acting the same). Some other awk implementation have different bugs, they may work differently because == will do a numeric comparison, etc. -- anyways, my point stands: your trick is not reliable. –  Feb 05 '19 at 17:41
2

As others have said, there is no -z test in awk, and the -z test in the shell tests for empty strings, not integers.

In awk you would do the following to test whether a variable is empty (and output a zero if it is, or its value if it's not):

if (value == "")
    print 0
else
    print value

or,

print (value == "" ? 0 : value)

For example:

$ awk -F '\t' '{ print ($1 == "" ? 0 : $1) }' file

to print a zero for those lines whose first tab-delimited value in the input is empty, and the actual value otherwise.

Possibly related (if you want to find the type of a variable in awk):

Kusalananda
  • 333,661
1

try

/bin/awk '{if( x$1 == x){print "0"}else{print $1}}' script  

there is no -z option in awk.

Archemar
  • 31,554
  • that will only check if $1 is non empty (ie is not ""), which you could do just as well with if($1) ... –  Feb 05 '19 at 08:35
  • 1
    @pizdelect if ($1) would not trigger if $1 is zero. – Kusalananda Feb 05 '19 at 08:35
  • @Kusalananda not if it's "0". –  Feb 05 '19 at 08:36
  • 1
    @pizdelect The test if ($1) would not test whether $1 is empty. It would test whether $1 is non-zero. That's what I mean. – Kusalananda Feb 05 '19 at 08:40
  • @Kusalananda Yeah, it's a bit of confusion. I know that echo 0 | awk '$1' won't print anything. echo | awk '{$1="0";if($1)print$1} will print 0, though. And it will test whether $1 is empty: echo :foo | awk -F: '$1' won't print anything, etc. –  Feb 05 '19 at 08:42