Bash脚本Awk-if语句

Bash脚本Awk-if语句,bash,awk,Bash,Awk,给定一个记录格式的输入文件。。。 ID,名字,姓氏,分数1,分数2,分数3,分数。。 重要提示:文件中将有大量记录,而不仅仅是一行 我希望能够提供输出格式,如。。 ID、平均分数、平均分数对应的等级字母 输入示例: 900123123 Joe Brown 100 90 80 900900900 Tyler Black 80 95 75 900231231 Stephen Williams 70 75 80 900111111 Andrew Smith 85 75 90 输出示例: 900123

给定一个记录格式的输入文件。。。 ID,名字,姓氏,分数1,分数2,分数3,分数。。 重要提示:文件中将有大量记录,而不仅仅是一行

我希望能够提供输出格式,如。。 ID、平均分数、平均分数对应的等级字母

输入示例:

900123123 Joe Brown 100 90 80
900900900 Tyler Black 80 95 75
900231231 Stephen Williams 70 75 80
900111111 Andrew Smith 85 75 90
输出示例:

900123123 90 A
900900900 83.3 B
900231231 75 C
900111111 83.3 B
我的问题是if语句,以确定分配哪个等级字母。这是我目前的代码:

#!/bin/bash
awk '
BEGIN {FS=OFS=" "}
{
sum=0; average=0
for(i=3;i<=NF;i++)
        {sum+=$i;}
average = (sum/(NF-3))
if (average -ge 90)
        print $1, $2, $3, average, " A";
else if(average -ge 80 && -le 90)
        print $1, $2, $3, average, " B";
else if(average -ge 70 && -le 80)
        print $1, $2, $3, average, " C";
else if(average -ge 60 && -le 70)
        print $1, $2, $3, average, " D";
else
        print $1, $2, $3, average, "F";
}' grades.txt
为什么即使平均值小于90,第一个if语句每次都会被命中?我们之所以知道这一点,是因为它在print语句中使用,并打印出带有任意数字的。
此外,我不知道为什么输出0 A,以及这可能是什么原因。

有两个问题:


-ge/-le代表bash,而awk是一种单独的编程语言,使用>=和有两个问题:


-ge/-le代表bash,而awk是一种单独的编程语言,它使用>=和这个带系数的awk脚本应该适合您:

#!/bin/bash
awk '{
sum=0;
for(i=3;i<=NF;i++)
        {sum+=$i;}
average = (sum/(NF-3));
avgstr = sprintf("%s%s%s%s%s%s%.2f", $1, OFS, $2, OFS, $3, OFS, average);
if (average >= 90)
        print avgstr, "A";
else if(average >= 80 && average <= 90)
        print avgstr, "B";
else if(average >= 70 && average <= 80)
        print avgstr, "C";
else if(average >= 60 && average <= 70)
        print avgstr, "D";
else
        print avgstr, "F";
}' grades.txt

此分区awk脚本应适用于您:

#!/bin/bash
awk '{
sum=0;
for(i=3;i<=NF;i++)
        {sum+=$i;}
average = (sum/(NF-3));
avgstr = sprintf("%s%s%s%s%s%s%.2f", $1, OFS, $2, OFS, $3, OFS, average);
if (average >= 90)
        print avgstr, "A";
else if(average >= 80 && average <= 90)
        print avgstr, "B";
else if(average >= 70 && average <= 80)
        print avgstr, "C";
else if(average >= 60 && average <= 70)
        print avgstr, "D";
else
        print avgstr, "F";
}' grades.txt

你的第一个条件是:

if (average -ge 90)
正如@thatotherguy指出的,-ge是一个shell构造,在awk中的等价物是>=。你的声明如下:

if ( (average - ge) 90 )
也就是说:从变量平均值中减去名为ge的未赋值变量的数值,即0,然后将字符串90连接到结果,例如,如果平均值为70,则其读数为:

if ( (70 - 0) 90 )
在减法之后是:

if ( 70 90 )
在连接之后是:

if ( 7090 )
这是一个真实的条件,因此您的脚本将始终执行后续的代码行,因为无论减法的结果是什么,您总是将其与90相关,并最终得到非零和非空的结果

输出末尾的0 A几乎可以肯定,因为输入文件末尾有一个空行。您可以通过在进入操作块之前测试NF来防止这种情况

以下是关于如何编写脚本的建议:

awk 'NF {
    sum=0
    for(i=3;i<=NF;i++)
        sum+=$i
    average = sum/(NF-3)
    if      (average >= 90) grade = "A"
    else if (average >= 80) grade = "B"
    else if (average >= 70) grade = "C"
    else if (average >= 60) grade = "D"
    else                    grade = "F"
    print $1, $2, $3, average, grade
}' grades.txt

当您处于测试平均值>=90的条件的其他部分时,&&average<90没有点测试。

您的第一个条件是:

if (average -ge 90)
正如@thatotherguy指出的,-ge是一个shell构造,在awk中的等价物是>=。你的声明如下:

if ( (average - ge) 90 )
也就是说:从变量平均值中减去名为ge的未赋值变量的数值,即0,然后将字符串90连接到结果,例如,如果平均值为70,则其读数为:

if ( (70 - 0) 90 )
在减法之后是:

if ( 70 90 )
在连接之后是:

if ( 7090 )
这是一个真实的条件,因此您的脚本将始终执行后续的代码行,因为无论减法的结果是什么,您总是将其与90相关,并最终得到非零和非空的结果

输出末尾的0 A几乎可以肯定,因为输入文件末尾有一个空行。您可以通过在进入操作块之前测试NF来防止这种情况

以下是关于如何编写脚本的建议:

awk 'NF {
    sum=0
    for(i=3;i<=NF;i++)
        sum+=$i
    average = sum/(NF-3)
    if      (average >= 90) grade = "A"
    else if (average >= 80) grade = "B"
    else if (average >= 70) grade = "C"
    else if (average >= 60) grade = "D"
    else                    grade = "F"
    print $1, $2, $3, average, grade
}' grades.txt

当您处于测试平均值>=90的条件的其他部分时,没有对&&average<90进行点测试。

此外,将打印因素排除在条件之外,只需将等级字母分配给变量即可。此外,在条件之外考虑打印,只需将分数字母分配给变量。使用此选项,我的输出仍然打印出一条额外记录,代码为:-0.00 FI。我的答案中提供了awk脚本的输出。抱歉,发现了我的问题。它在我的输入文件中。使用它,我的输出仍然打印出一条代码为:-0.00的额外记录。FI在我的回答中提供了awk脚本的输出。很抱歉,发现了我的问题。它在我的输入文件中。