3

在过去的考试论文中,我有一个问题:

月份可以用不同的方式表示,例如数字(1、2、...、12)或三个字母的月份名称(Jan、Feb、...、Dec)。建议如何使用 awk 中的关联数组将三个字母的月份名称转换为月份编号,反之亦然,将月份编号转换为三个字母的月份名称。

所以我想我会使用格式中的关联数组,比如月份的输入是 1 美元:

number_to_month["Jan"] = 1;
print number_to_month[$1]

但对我来说,这似乎并没有很好地利用关联数组的力量,而且我必须每个月在数组中手动​​初始化。

我还有哪些其他选择?

4

5 回答 5

6

内置split函数在这里是你的朋友,循环可以将 name-from-number 版本复制到 number-from-name 中:

BEGIN {
    split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec",month)
    for (i in month) {
        month_nums[month[i]]=i
    }
}
END {
    for (i in month) {
        print i "\t" month[i]
    }
    for (m in month_nums) {
        print m "\t" month_nums[m]
    }
}

BEGIN块显示了如何做到这一点。然后END阻止只是让您验证它。

我得到的输出(使用 gawk 4.0.1)是:

4       Apr
5       May
6       Jun
7       Jul
8       Aug
9       Sep
10      Oct
11      Nov
12      Dec
1       Jan
2       Feb
3       Mar
Feb     2
Sep     9
Jan     1
May     5
Apr     4
Oct     10
Dec     12
Nov     11
Jul     7
Mar     3
Aug     8
Jun     6

请注意由于无法强制数组循环上的访问顺序而引起的通常的尴尬(嘿!AWKwardness )。for

于 2013-01-15T16:31:29.520 回答
2

如果您不想手动初始化数组,一种选择是:

echo | awk '{x=mktime("2013 01 01 0 0 0"); for(i=0;i<12;i++){s=strftime("%b",x+((31*i)*86400)); m[s]=i+1;n[i+1]=s;}}'

这将创建 2 个数组 m 和 n,其中 m 是数组,其中索引是月份名称,值是月份编号,n 数组反之亦然。

于 2013-01-15T16:42:03.627 回答
1
$ cat tst.awk
BEGIN {
   mths="JanFebMarAprMayJunJulAugSepOctNovDec"

   name="Mar"; print name " -> " (match(mths,name)+2)/3
   name="Sep"; print name " -> " (match(mths,name)+2)/3

   nbr=3;      print nbr  " -> " substr(mths,(nbr*3)-2,3)
   nbr=9;      print nbr  " -> " substr(mths,(nbr*3)-2,3)
}

$ awk -f tst.awk
Mar -> 3
Sep -> 9
3 -> Mar
9 -> Sep

这是@dmckee 的脚本修改后产生有序输出:

$ cat tst2.awk
BEGIN {
    n = split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec",month)
    for (i in month) {
        month_nums[month[i]]=i
    }

    for (i=1; i<=n; i++) {
        print i "\t" month[i]
    }
    for (i=1; i<=n; i++) {
        m = month[i]
        print m "\t" month_nums[m]
    }
}
$ awk -f tst2.awk
1       Jan
2       Feb
3       Mar
4       Apr
5       May
6       Jun
7       Jul
8       Aug
9       Sep
10      Oct
11      Nov
12      Dec
Jan     1
Feb     2
Mar     3
Apr     4
May     5
Jun     6
Jul     7
Aug     8
Sep     9
Oct     10
Nov     11
Dec     12
于 2013-01-15T19:33:00.923 回答
0

当他们提到 awk 时,我认为这些月份的详细信息和整数映射保存在数据文件中,例如

1 JAN JANUARY jan
2 FEB FEBRUARY feb
...

等等

你可以使用 awk

awk '/JAN/ {print $1}' temp.txt
于 2013-01-15T16:31:22.313 回答
0

这是另一个使用几个辅助函数的方法:

awk '
    BEGIN { 
        j = 0
        for (i=1; i<=34; i+=3) {
            months[substr("JanFebMarAprMayJunJulAugSepOctNovDec",i,3)] = ++j
        }
    }
    function month2num(month) {
        return (month in months ? months[month] : -1)
    }
    function num2month(n) {
        for (month in months) {
            if (months[month] == n)
                return month
        }
        return ""
    }
    BEGIN {
        print "Jan: " month2num("Jan")
        print "Dec: " month2num("Dec")
        print "Foo: " month2num("Foo")
        print "3: " num2month(3)
        print "12: " num2month(12)
        print "14: " num2month(14)
    }
'
于 2013-01-15T20:57:48.543 回答