如何使用 SED 或 AWK 代替 GREP,因为它在 shell 脚本中花费大量时间

如何使用 SED 或 AWK 代替 GREP,因为它在 shell 脚本中花费大量时间

我编写了下面的代码来提取测试用例名称和 PASSED/FAILED 状态。 测试用例日志如下:: 中间有很多行。

我只想提取测试用例名称(例如 A_HL_INT_GPRS_CGDSCONT_0000 以及它的“通过”或“失败”状态)。

另外,另一个问题是:我使用了 grep 来执行 shell 脚本,这需要更长的时间。

我需要使用 AWK 或 SED 命令来解决以下问题。

我还需要的一件事是:我需要打印所有失败的测试用例名称,例如:

failed testcases list:

A_HL_INT_GPRS_CGDCONT_0002 Failed
A_HL_INT_GPRS_CGDCONT_0003 Failed
A_HL_INT_GPRS_CGDCONT_0004 Failed
Begin of A_HL_INT_GPRS_CGDSCONT_0000 
Passed
End of A_HL_INT_GPRS_CGDSCONT_0000 
Begin of A_HL_INT_GPRS_CGDCONT_0002
FAILED
End of A_HL_INT_GPRS_CGDCONT_0002 
#! /bin/bash
echo "Enter the logfilename : "
read logfilename
echo "Entered name : $logfilename"
echo "outside the while loop"
let success=0
let failure=0
let total=0
DONE=false
until $DONE; do
read line || DONE=true
    echo "$line" | grep "Begin of "
    if (echo "$line" | grep -i "PASSED") then
        ((success++))
    fi
    if (echo "$line" | grep -i "FAILED") then
        ((failure++))
    fi
    if (echo "$line" | grep "End of ") then
        ((total++))
    fi  
done < "$logfilename"   
echo "Total testcases : $total"
echo "Total testcase with Success : $success"
echo "Total testcase with Failure : $failure"

嗨博多:

我添加了以下与您的代码一致的行:

#! /bin/bash
echo -n "Enter the logfilename : "
read logfilename
echo "Entered name : $logfilename"
echo "outside the while loop"

awk 'BEGIN { IGNORECASE=1; }
/^begin of / { print; count=1; passed=failed=0;}
/^end of / { count=0; totalcount++; if(failed)failcount++;else if(passed)passcount++;}
/passed/ && count { passed=1; }
/failed/ && count { failed=1; }
END {
  print "Total testcases : " totalcount;
  print "Total testcase with Success : " passcount;
  print "Total testcase with Failure : " failcount; }' "logfilename"

嗨乌鲁特尔,

您能否更正以下代码:我试图删除“Begin of TESTCASENAME”行,只是尝试将失败的测试用例存储在数组中,然后打印失败的测试用例列表。另外,我试图处理这种情况 - 如果日志文件不存在怎么办:

#! /bin/bash
declare -a arr
# if no command line argument is given
# set logfilename to : logfilename not specified
if [ -z $0 ]
then
  logfilename="*** Log filename not specified.***"
elif [ -n $1 ]
then
# otherwise make first arg as logfilename
  logfilename=$1
fi

echo "outside the while loop"
let success=0
let failure=0
let total=0
let fail=0
while read line; do
        case "$line" in
                *Begin\ of\ *)  echo $line;;
                *PASSED*)       ((success++));;
                *FAILED*)       ((failure++))
                    arr[$fail] = $line
                    echo "Shubhra added this line : ${arr[$fail]}"
                    ((fail++));;
                *End\ of\ *)    ((total++));;
        esac
done < "$logfilename"

echo "Total testcases : $total"
echo "Total testcase with Success : $success"
echo "Total testcase with Failure : $failure"
echo "failed testcase list:"
echo ${arr[@]}

答案1

这里的解决方案是在 shell 中使用内置命令,因为这样每行就不会执行多个 fork/exec,这相对非常昂贵。

我会这样做:

#! /bin/bash
echo -n "Enter the logfilename : "
read logfilename
echo "Entered name : $logfilename"
echo "outside the while loop"
let success=0
let failure=0
let total=0
failedtests=()

while read line; do
        case "$line" in
                *Begin\ of\ *)  echo $line
                                failedtests+=( ${line/Begin of /} )
                                ;;
                *PASSED*)       ((success++));;
                *FAILED*)       ((failure++));;
                *End\ of\ *)    ((total++));;
        esac
done < "$logfilename"

echo "Total testcases : $total"
echo "Total testcase with Success : $success"
echo "Total testcase with Failure : $failure"
echo "Failed tests:" ${failedtests[@]}

您可以用来case匹配全局模式。根据您的示例数据(其中有“通过”而不是您 grep 的“通过”)*每个模式的前导可以省略,但是有了它,它与 grep 用法完全匹配。

我还取消了该DONE变量,因为您无用地循环了最终的空字符串(由文件结尾产生)。

编辑:添加了收集和显示失败的测试。这些都收集在 bash 数组中failedtests。结果是删除了该字符串${line/Begin of /}的内容。line最后,数组的完整内容显示为${failedtests[@]}

答案2

如果您的 AWK 支持变量IGNORECASE来强制不区分大小写的比较,则可以使用以下脚本。 (GNU AWK,例如 Linux 上支持这一点。)

如果你的 AWK 不支持IGNORECASE,你可以

  • 将所有匹配模式修改为不区分大小写的模式,例如/[Pp][Aa][Ss][Ss][Ee][Dd]/代替/passed/等或
  • tolower使用具有要匹配的值的函数,例如tolower($0) ~ /passed/代替/passed/等。
awk 'BEGIN { IGNORECASE=1; }
/^begin of / { print; count=1; passed=failed=0;}
/^end of / { count=0; totalcount++; if(failed)failcount++;else if(passed)passcount++;}
/passed/ && count { passed=1; }
/failed/ && count { failed=1; }
END {
  print "Total testcases : " totalcount;
  print "Total testcase with Success : " passcount;
  print "Total testcase with Failure : " failcount; }' logfile

使用此输入(在文件中logfile

Begin of A_HL_INT_GPRS_CGDSCONT_0000
Passed
foo
End of A_HL_INT_GPRS_CGDSCONT_0000
Begin of A_HL_INT_GPRS_CGDCONT_0002
bar
passed
FAILED
End of A_HL_INT_GPRS_CGDCONT_0002
Begin of foo
failed
End of bar
foo
Passed
FAILED
bar

我得到这个结果

Begin of A_HL_INT_GPRS_CGDSCONT_0000
Begin of A_HL_INT_GPRS_CGDCONT_0002
Begin of foo
Total testcases : 3
Total testcase with Success : 1
Total testcase with Failure : 2

注意:
脚本的编辑版本在和行之间计数passedfailed仅计数一次,优先于。 该脚本不会检查和中的标识符是否匹配。begin of ...end of ...failedpassed
begin of ...end of ...

相关内容