Home > Archive > AWK > November 2004 > associative arrays, weird behavior of
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
associative arrays, weird behavior of
|
|
| Greg Nowak 2004-11-22, 8:55 am |
| I'm having a problem using associative arrays.
What I want to do is set up some arrays in BEGIN as lookup tables to
be used later in line processing. (Yes, I'm a newbie, please tell me
if I should be doing this differently)
Here's a tiny example:
# test awk
BEGIN {
mct[Jan]=31
mct[Feb]=28
ctm[1]=31
ctm[2]=28
print "Output mct: ", mct[Jan], " Output ctm: ", ctm[1]
}
When I run this, I get:
Output mct: 28 Output ctm: 31
Whereas I expect to get:
Output mct: 31 Output ctm: 31
This has been tested on multiple versions, so I realize it's probably
not an implementation issue.
In words, it looks like when I try to use a string as an index,
whenever I try to get a value from that array, I get the last value
defined for that array -- no matter what index I use.
(If anybody cares about the implementation, I'm trying to find a quick
way of translating day and month names to numerical values in
login.log... Even if there's a better way to do that, I'm curious
about why associative arrays work this way)
Can somebody tell me what I'm missing?
Thanks!
| |
| John DuBois 2004-11-22, 8:55 am |
| In article <840f61b8.0411171737.496e3c2d@posting.google.com>,
Greg Nowak <greg_nowak@mcgraw-hill.com> wrote:
># test awk
>
>BEGIN {
>
>mct[Jan]=31
>mct[Feb]=28
>
>ctm[1]=31
>ctm[2]=28
>
>print "Output mct: ", mct[Jan], " Output ctm: ", ctm[1]
>}
Jan and Feb aren't strings, they're variables, both of which are going to get
an initial null value and thus give the same array index. You want
mct["Jan"]=31
mct["Feb"]=28
....
print "Output mct: ", mct["Jan"], " Output ctm: ", ctm[1]
And yes, this is a fine way of looking up month information by monthname.
John
--
John DuBois spcecdt@armory.com KC6QKZ/AE http://www.armory.com/~spcecdt/
| |
| Ed Morton 2004-11-22, 8:55 am |
|
Greg Nowak wrote:
> I'm having a problem using associative arrays.
>
> What I want to do is set up some arrays in BEGIN as lookup tables to
> be used later in line processing. (Yes, I'm a newbie, please tell me
> if I should be doing this differently)
>
> Here's a tiny example:
>
> # test awk
>
> BEGIN {
>
> mct[Jan]=31
> mct[Feb]=28
>
> ctm[1]=31
> ctm[2]=28
>
> print "Output mct: ", mct[Jan], " Output ctm: ", ctm[1]
> }
>
> When I run this, I get:
>
> Output mct: 28 Output ctm: 31
>
> Whereas I expect to get:
>
> Output mct: 31 Output ctm: 31
>
> This has been tested on multiple versions, so I realize it's probably
> not an implementation issue.
No, it's you ;-). Jan and Feb as used above are variables and so have
the initial value of zero or null depending how you use them. Since
you're using them to index an array, they're assumed to be integers and
so have the value zero, so these lines:
mct[Jan]=31
mct[Feb]=28
are both equivalent to:
mct[0]=31
mct[0]=28
and this:
print "Output mct: ", mct[Jan]
is equivalent to:
print "Output mct: ", mct[0]
What you really wanted, I suspect is to do this:
mct["Jan"]=31
mct["Feb"]=28
....
print "Output mct: ", mct["Jan"]
so that instead of indexing mct with a variable whos value is zero,
you're indexing it with a specific string. Alternatively, you could do this:
Jan=1
Feb=2
mct[Jan]=31
mct[Feb]=28
....
print "Output mct: ", mct[Jan]
> In words, it looks like when I try to use a string as an index,
> whenever I try to get a value from that array, I get the last value
> defined for that array -- no matter what index I use.
>
> (If anybody cares about the implementation, I'm trying to find a quick
> way of translating day and month names to numerical values in
> login.log... Even if there's a better way to do that, I'm curious
> about why associative arrays work this way)
>
Then you probably do want to do the indexing by strings, e.g.:
awk 'BEGIN{mct["Jan"]=31;mct["Feb"]=28;...}{print mct[$1]}' file
assuming that the month name is in the first column of "file".
Ed.
> Can somebody tell me what I'm missing?
>
> Thanks!
| |
| Kenny McCormack 2004-11-22, 8:55 am |
| In article <wqOdnc3u0a-zYgbcRVn-sw@comcast.com>,
Ed Morton <morton@lsupcaemnt.com> wrote:
>No, it's you ;-). Jan and Feb as used above are variables and so have
>the initial value of zero or null depending how you use them. Since
>you're using them to index an array, they're assumed to be integers and
>so have the value zero, so these lines:
ITYM, they're assumed to be strings and have the value ""
| |
| Kenny McCormack 2004-11-22, 8:55 am |
| In article <DvGdnQTYqtcKiAHcRVn-ug@comcast.com>,
Ed Morton <morton@lsupcaemnt.com> wrote:
>
>
>Kenny McCormack wrote:
>
>Yup, you're right:
>
>PS1> echo "y" | awk '{x[a]=$1; print x[0] ":" x[""]}'
>:y
>
>I'd never have expected an array index to be assumed to be a string, I
>guess I'm still somewhat stuck in my C paradigm. Thanks for catching it.
It is a basic part of the definition of the AWK language.
Array indexes are strings. Always.
| |
| Eric Pement 2004-11-22, 8:55 pm |
| greg_nowak@mcgraw-hill.com (Greg Nowak) wrote in message news:<840f61b8.0411171737.496e3c2d@posting.google.com>...
> I'm having a problem using associative arrays.
>
> What I want to do is set up some arrays in BEGIN as lookup tables to
> be used later in line processing. (Yes, I'm a newbie, please tell me
> if I should be doing this differently)
>
> Here's a tiny example:
>
> # test awk
>
> BEGIN {
>
> mct[Jan]=31
> mct[Feb]=28
>
> ctm[1]=31
> ctm[2]=28
>
> print "Output mct: ", mct[Jan], " Output ctm: ", ctm[1]
> }
>
> When I run this, I get:
>
> Output mct: 28 Output ctm: 31
>
> Whereas I expect to get:
>
> Output mct: 31 Output ctm: 31
The problem, as has already been noted, is that the array["key"] needs
to be put in quotes. If it is an unquoted word, it is treated as a
variable name, which resolves (in your case) to an *undefined*
variable.
To address your interest in parsing month names and days, here is one
way that I find clear and easy to read. There are others, as you have
already seen, but this is fairly concise and it may fit your needs:
BEGIN {
split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec", name, " ")
split("31 28 31 30 31 30 31 31 30 31 30 31 ", ctm, " ")
for (i=1; i <= 12; i++)
mct[name[i]] = ctm[i]
print "The 11th month is " name[11] "."
print "The 11th month has " ctm[11] " days."
print "The month of Nov has " mct["Nov"] " days."
print "The 12th month is " name[12] "."
print "The 12th month has " ctm[12] " days."
print "The month of Dec has " mct["Dec"] " days."
}
Kind regards,
Eric Pement
|
|
|
|
|