Shell 如何在awk中匹配列名并查找列位置?

Shell 如何在awk中匹配列名并查找列位置?,shell,unix,awk,Shell,Unix,Awk,我正在尝试使用awk解析一些csv文件。我不熟悉shell脚本和awk。 我正在处理的csv文件如下所示: fnName,minAccessTime,maxAccessTime getInfo,300,600 getStage,600,800 getStage,600,800 getInfo,250,620 getInfo,200,700 getStage,700,1000 getInfo,280,600 我需要找到不同函数的平均访问时间 我一直在与awk合作,并且能够获得平均时间,前提是指定

我正在尝试使用awk解析一些csv文件。我不熟悉shell脚本和awk。 我正在处理的csv文件如下所示:

fnName,minAccessTime,maxAccessTime
getInfo,300,600
getStage,600,800
getStage,600,800
getInfo,250,620
getInfo,200,700
getStage,700,1000
getInfo,280,600
我需要找到不同函数的平均访问时间

我一直在与awk合作,并且能够获得平均时间,前提是指定了准确的列数,如$2、

但是,我需要一个通用脚本,如果在命令参数中输入“minAccessTime”,则需要该脚本打印平均访问时间(而不是在使用awk时显式指定$2或$3)

我一直在谷歌上搜索这一点,并在各种论坛上看到了这一点,但它们似乎都不起作用。 有人能告诉我怎么做吗?这会有很大的帮助


提前谢谢

这个
awk
脚本应该给你想要的一切

它首先通过使用作为
COLM
变量传入的名称并对照第一行进行检查来评估您感兴趣的列。它将其转换为索引(如果找不到该列,则保留为默认的0)

然后,它基本上贯穿输入文件中的所有其他行。在所有其他行上(假设您指定了一个有效列),它会更新整个数据加上每个单独函数名的计数、总和、最小值和最大值

前者存储在
count
sum
min
max
中。后者存储在具有类似名称的关联数组中(附加
\u arr

然后,读取所有记录后,
END
部分输出信息

NR == 1 {
    for (i = 1; i <= NF; i++) {
        if ($i == COLM) {
            cidx = i;
        }
    }
}

NR > 1 {
    if (cidx > 0) {
        count++;
        sum += $cidx;
        if (count == 1) {
            min = $cidx;
            max = $cidx;
        } else {
            if ($cidx < min) { min = $cidx; }
            if ($cidx > max) { max = $cidx; }
        }

        count_arr[$1]++;
        sum_arr[$1] += $cidx;
        if (count_arr[$1] == 1) {
            min_arr[$1] = $cidx;
            max_arr[$1] = $cidx;
        } else {
            if ($cidx < min_arr[$1]) { min_arr[$1] = $cidx; }
            if ($cidx > max_arr[$1]) { max_arr[$1] = $cidx; }
        }
    }
}

END {
    if (cidx == 0) {
        print "Column '" COLM "' does not exist"
    } else {
        print "Overall:"
        print "   Total records = " count
        print "   Sum of column = " sum
        if (count > 0) {
            print "   Min of column = " min
            print "   Max of column = " max
            print "   Avg of column = " sum / count
        }
        for (task in count_arr) {
            print "Function " task ":"
            print "   Total records = " count_arr[task]
            print "   Sum of column = " sum_arr[task]
            print "   Min of column = " min_arr[task]
            print "   Max of column = " max_arr[task]
            print "   Avg of column = " sum_arr[task] / count_arr[task]
        }
    }
}
生成以下输出,我相对确定它将为您提供所需的所有可能的信息:

Overall:
   Total records = 7
   Sum of column = 2930
   Min of column = 200
   Max of column = 700
   Avg of column = 418.571
Function getStage:
   Total records = 3
   Sum of column = 1900
   Min of column = 600
   Max of column = 700
   Avg of column = 633.333
Function getInfo:
   Total records = 4
   Sum of column = 1030
   Min of column = 200
   Max of column = 300
   Avg of column = 257.5
对于“maxAccessTime”,您可以获得:

Overall:
   Total records = 7
   Sum of column = 5120
   Min of column = 600
   Max of column = 1000
   Avg of column = 731.429
Function getStage:
   Total records = 3
   Sum of column = 2600
   Min of column = 800
   Max of column = 1000
   Avg of column = 866.667
Function getInfo:
   Total records = 4
   Sum of column = 2520
   Min of column = 600
   Max of column = 700
   Avg of column = 630
对于
xyzy
(一个不存在的列),您将看到:

Column 'xyzzy' does not exist

这个
awk
脚本应该为您提供您想要的一切

它首先通过使用作为
COLM
变量传入的名称并对照第一行进行检查来评估您感兴趣的列。它将其转换为索引(如果找不到该列,则保留为默认的0)

然后,它基本上贯穿输入文件中的所有其他行。在所有其他行上(假设您指定了一个有效列),它会更新整个数据加上每个单独函数名的计数、总和、最小值和最大值

前者存储在
count
sum
min
max
中。后者存储在具有类似名称的关联数组中(附加
\u arr

然后,读取所有记录后,
END
部分输出信息

NR == 1 {
    for (i = 1; i <= NF; i++) {
        if ($i == COLM) {
            cidx = i;
        }
    }
}

NR > 1 {
    if (cidx > 0) {
        count++;
        sum += $cidx;
        if (count == 1) {
            min = $cidx;
            max = $cidx;
        } else {
            if ($cidx < min) { min = $cidx; }
            if ($cidx > max) { max = $cidx; }
        }

        count_arr[$1]++;
        sum_arr[$1] += $cidx;
        if (count_arr[$1] == 1) {
            min_arr[$1] = $cidx;
            max_arr[$1] = $cidx;
        } else {
            if ($cidx < min_arr[$1]) { min_arr[$1] = $cidx; }
            if ($cidx > max_arr[$1]) { max_arr[$1] = $cidx; }
        }
    }
}

END {
    if (cidx == 0) {
        print "Column '" COLM "' does not exist"
    } else {
        print "Overall:"
        print "   Total records = " count
        print "   Sum of column = " sum
        if (count > 0) {
            print "   Min of column = " min
            print "   Max of column = " max
            print "   Avg of column = " sum / count
        }
        for (task in count_arr) {
            print "Function " task ":"
            print "   Total records = " count_arr[task]
            print "   Sum of column = " sum_arr[task]
            print "   Min of column = " min_arr[task]
            print "   Max of column = " max_arr[task]
            print "   Avg of column = " sum_arr[task] / count_arr[task]
        }
    }
}
生成以下输出,我相对确定它将为您提供所需的所有可能的信息:

Overall:
   Total records = 7
   Sum of column = 2930
   Min of column = 200
   Max of column = 700
   Avg of column = 418.571
Function getStage:
   Total records = 3
   Sum of column = 1900
   Min of column = 600
   Max of column = 700
   Avg of column = 633.333
Function getInfo:
   Total records = 4
   Sum of column = 1030
   Min of column = 200
   Max of column = 300
   Avg of column = 257.5
对于“maxAccessTime”,您可以获得:

Overall:
   Total records = 7
   Sum of column = 5120
   Min of column = 600
   Max of column = 1000
   Avg of column = 731.429
Function getStage:
   Total records = 3
   Sum of column = 2600
   Min of column = 800
   Max of column = 1000
   Avg of column = 866.667
Function getInfo:
   Total records = 4
   Sum of column = 2520
   Min of column = 600
   Max of column = 700
   Avg of column = 630
对于
xyzy
(一个不存在的列),您将看到:

Column 'xyzzy' does not exist

如果我正确理解了这些要求,那么您需要列的平均值,并且希望按名称指定列

尝试以下脚本(
avg.awk
):

开始{
FS=“,”;
}
NR==1{
对于(i=1;i 1&&$1~选定的\u FNAME{
总和[$1]=总和[$1]+$SELECTED\u COL;
计数[$1]=计数[$1]+1;
}
结束{
(f合计){
printf(“平均%s为%s:%d\n”,选择的_字段,f,总和[f]/计数[f]);
}
}
然后像这样调用脚本

awk -v SELECTED_FIELD=minAccessTime -f avg.awk < data.csv
awk-v SELECTED_FIELD=minAccessTime-f avg.awk

awk-v SELECTED_FIELD=maxAccessTime-f avg.awk

awk-v SELECTED_FIELD=maxAccessTime-v SELECTED_FNAME=getInfo-f avg.awk
编辑:

重写为按函数名分组(假定为第一个字段)

编辑2:


重写以允许附加参数按函数名(假定为第一个字段)进行筛选。

如果我正确理解了要求,您需要列的平均值,并且希望按名称指定列

尝试以下脚本(
avg.awk
):

开始{
FS=“,”;
}
NR==1{
对于(i=1;i 1&&$1~选定的\u FNAME{
总和[$1]=总和[$1]+$SELECTED\u COL;
计数[$1]=计数[$1]+1;
}
结束{
(f合计){
printf(“平均%s为%s:%d\n”,选择的_字段,f,总和[f]/计数[f]);
}
}
然后像这样调用脚本

awk -v SELECTED_FIELD=minAccessTime -f avg.awk < data.csv
awk-v SELECTED_FIELD=minAccessTime-f avg.awk

awk-v SELECTED_FIELD=maxAccessTime-f avg.awk

awk-v SELECTED_FIELD=maxAccessTime-v SELECTED_FNAME=getInfo-f avg.awk
编辑:

重写为按函数名分组(假定为第一个字段)

编辑2:


重写以允许按函数名筛选其他参数(假定为第一个字段)

我已将awk脚本重写为按函数名分组,我认为这更符合您的要求。@beny23..是的..这正是我所需要的..但此脚本提供了csv文件中每个函数的平均时间。不过,我还想指定函数名以获得结果…以前我是通过使用模式ma来实现的正在选择要处理的特定记录。但使用您提供的脚本,我无法执行相同的操作。您是否也可以提供更新来处理此问题?谢谢。我已将awk脚本重写为按函数名分组,我认为这更符合您的要求。@beny23。是的。这正是我需要的。但此脚本提供了csv文件中每个函数的平均时间。但是,我还想指定函数名以获得结果…以前我是通过模式匹配来选择特定记录进行处理的。但是使用提供的脚本u,我无法执行相同的操作。请向dea提供更新