-1

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?

BlackCrystal
  • 716
  • 14
  • 39

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
1

try

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

there is no -z option in awk.

Archemar
  • 31,183
  • 18
  • 69
  • 104
  • 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
1

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
  • 320,670
  • 36
  • 633
  • 936