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
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:
- 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.