How to check if a variable is an array?
Asked Answered
W

1

4

I was playing with PROCINFO and its sorted_in index to be able to control the array transversal.

Then I wondered what are the contents of PROCINFO, so I decided to go through it and print its values:

$ awk 'BEGIN {for (i in PROCINFO) print i, PROCINFO[i]}'
ppid 7571
pgrpid 14581
api_major 1
api_minor 1
group1 545
gid 545
group2 1000
egid 545
group3 10004
awk: cmd. line:1: fatal: attempt to use array `PROCINFO["identifiers"]' in a scalar context

As you see, it breaks because there is -at least- one item that it is also an array itself.

The fast workaround is to skip this one:

awk 'BEGIN {for (i in PROCINFO) {if (i!="identifiers") {print i, PROCINFO[i]}}}'

However it looks a bit hacky and would like to have something like

awk 'BEGIN {for (i in PROCINFO) {if (!(a[i] is array)) {print i, PROCINFO[i]}}}'
                                     ^^^^^^^^^^^^^^^^

Since there is not a thing like a type() function to determine if a variable is an array or a scalar, I wonder: is there any way to check if an element is an array?

I was thinking in something like going through it with a for and catching the possible error, but I don't know how.

$ awk 'BEGIN{a[1]=1; for (i in a) print i}'
1
$ awk 'BEGIN{a=1; for (i in a) print i}'
awk: cmd. line:1: fatal: attempt to use scalar `a' as an array
$ awk 'BEGIN{a[1]=1; print a}'
awk: cmd. line:1: fatal: attempt to use array `a' in a scalar context
Whitebait answered 22/12, 2015 at 10:47 Comment(0)
C
4

In GNU Awk, there's an answer, but the recommended approach depends on what version you are running.


From GNU Awk 4.2, released in October 2017, there is a new function typeof() to check this, as indicated in the release notes from the beta release:

  1. The new typeof() function can be used to indicate if a variable or array element is an array, regexp, string or number. The isarray() function is deprecated in favor of typeof().

So now you can say:

$ awk 'BEGIN { a[1] = "a"; print typeof(a) }'
array

And perform the check as follows:

$ awk 'BEGIN { a = "a"; if (typeof(a) == "array") print "yes" }'    
$ awk 'BEGIN { a[1] = "a"; if (typeof(a) == "array") print "yes" }'
yes

In older versions, you can use isarray():

$ awk 'BEGIN { a = "a"; if (isarray(a)) print "yes" }'
$ awk 'BEGIN { a[1] = "a"; if (isarray(a)) print "yes" }'
yes

From the man page:

isarray(x)
    Return true if x is an array, false otherwise.
Cleveite answered 22/12, 2015 at 11:2 Comment(3)
This is really it! From the manual isarray() is meant for use in two circumstances. The first is when traversing a multidimensional array: you can test if an element is itself an array or not., exactly my case!Whitebait
From GNU awk 4.2 we now have typeof()!Whitebait
Nice. We'll add the link to typeof() as soon as it gets into the GNU awk docs.Whitebait

© 2022 - 2024 — McMap. All rights reserved.