Code Comments
Programming Forum and web based access to our favorite programming groups.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!
Post Follow-up to this messageIn 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 ge
t
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/
Post Follow-up to this message
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!
Post Follow-up to this messageIn 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 ""
Post Follow-up to this messageIn 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.
Post Follow-up to this messagegreg_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
Post Follow-up to this messagePowered by vBulletin
Copyright 2000-2006 Jelsoft Enterprises Limited.