Bash 减少awk通过次数

Bash 减少awk通过次数,bash,awk,Bash,Awk,我在Teradata数据库上工作,并有一个空间检查脚本。脚本应该根据脚本开始时定义的空间使用值将标志提升为“严重”或“警告” 我的示例SQL文件输出为(DatabaseOutput.log),文件如下所示,该文件用作awk块的输入 ### Some multiline Database query, resulting in Database Space usage *** Query completed. 11 rows found. 4 columns returned. *** To

我在Teradata数据库上工作,并有一个空间检查脚本。脚本应该根据脚本开始时定义的空间使用值将标志提升为“严重”或“警告”

我的示例SQL文件输出为(DatabaseOutput.log),文件如下所示,该文件用作awk块的输入

### Some multiline Database query, resulting in Database Space usage

 *** Query completed. 11 rows found. 4 columns returned.
 *** Total elapsed time was 11 seconds.

## Output of the query, I am interested in DatabaseName, Perc2, MaxPerm

DatabaseName                                          Perc                    Perc2      MaxPerm
----------------------------------------------------  ----------------------  -------  -----------
AAA                                                   9.21899768137583E-001    92.19     10102320
BBB                                                   9.19923819717036E-001    91.99       524160
CCC                                                   9.17517791271651E-001    91.75      1687440
DDD                                                   9.15820363471060E-001    91.58       816720
EEE                                                   9.09293748338489E-001    90.93       149760
FFF                                                   9.07840905921109E-001    90.78      6934080
GGG                                                   9.04946085680591E-001    90.49      7273440
HHH                                                   8.54498111733230E-001    85.45      2538960
III                                                   8.22783559253080E-001    82.28      7598400
JJJ                                                   8.02181524253446E-001    80.22      8077680

+---------+---------+---------+---------+---------+---------+---+---------+-
所需输出为

WARNING                           AAA     92.19  10102320
WARNING                           BBB     91.99    524160
WARNING                           CCC     91.75   1687440
WARNING                           DDD     91.58    816720
WARNING                           EEE     90.93    149760
WARNING                           FFF     90.78   6934080
WARNING                           GGG     90.49   7273440
我有三个通行证的工作awk代码。。可以减少到一个awk通行证吗

工作awk代码:

cLvlCRIT=95
cLvlWARN=90

cat DatabaseOutput.log |
    awk '/-------------------/,/^$/' | # captures output block; it excludes query, logon, logoff information and header line but keeps separator's line.
        awk '{if (NR >= 2) {print}}' | # removes separator line, prints all lines from line 2 to EOF
            awk -v lLvlCRIT=$cLvlCRIT -v lLvlWARN=$cLvlWARN ' {
            if ( $1 != "StartCapture" && $3 >= lLvlCRIT ) {
                printf("%11s%30s%10s%10s\n", "CRITICAL",$1,$3,$4)
               }
            if ( $1 != "StartCapture" && $3 >= lLvlWARN && $3 < lLvlCRIT ) {
               printf("%11s%30s%10s%10s\n", "WARNING",$1,$3,$4)
              }
} '
cLvlCRIT=95
cLvlWARN=90
cat DatabaseOutput.log|
awk'/----------------/,/^$/'|#捕获输出块;它不包括查询、登录、注销信息和标题行,但保留分隔符的行。
awk'{if(NR>=2){print}}}|#删除分隔线,打印从第2行到EOF的所有行
awk-v lLvlCRIT=$cLvlCRIT-v lLvlWARN=$cLvlWARN'{
如果($1!=“StartCapture”&&&$3>=lLvlCRIT){
printf(“%11s%30s%10s%10s\n”、“严重”、“1美元、$3美元、$4”)
}
如果($1!=“StartCapture”&&&$3>=lLvlWARN&&&$3

提前谢谢

您的
awk
可能如下所示:

awk -v lLvlCRIT="$cLvlCRIT" -v lLvlWARN="$cLvlWARN" '
/^---/,/^$/ {
   if ( $0 ~ "^---" || $0 ~ "^$" ) next
   if ( $3 >= lLvlCRIT )
       printf("%11s%30s%10s%10s\n", "CRITICAL",$1,$3,$4)       
   else if ( $3 >= lLvlWARN )
       printf("%11s%30s%10s%10s\n", "WARNING",$1,$3,$4)               
}' DatabaseOutput.lo


awk
中指定模式范围可能很棘手,而标志是首选方法。有关更多信息,请参阅。

这将根据您的示例输入完成

 #!/bin/bash

    cLvlCRIT=95
    cLvlWARN=90

   grep -E '^[a-zA-Z]+[ ]+[0-9.]+' DatabaseOutput.log |
         awk -v lLvlCRIT=$cLvlCRIT -v lLvlWARN=$cLvlWARN ' {
                if ( $1 != "StartCapture" && $3 >= lLvlCRIT ) {
                    printf("%11s%30s%10s%10s\n", "CRITICAL",$1,$3,$4)
                   }
                if ( $1 != "StartCapture" && $3 >= lLvlWARN && $3 < lLvlCRIT ) {
                   printf("%11s%30s%10s%10s\n", "WARNING",$1,$3,$4)
                  }
    } '
#/bin/bash
cLvlCRIT=95
cLvlWARN=90
grep-E'^[a-zA-Z]+[]+[0-9.]+'DatabaseOutput.log|
awk-v lLvlCRIT=$cLvlCRIT-v lLvlWARN=$cLvlWARN'{
如果($1!=“StartCapture”&&&$3>=lLvlCRIT){
printf(“%11s%30s%10s%10s\n”、“严重”、“1美元、$3美元、$4”)
}
如果($1!=“StartCapture”&&&$3>=lLvlWARN&&&$3

问候

您可以使用标志在awk中获取块:

awk -v lLvlCRIT="$cLvlCRIT" -v lLvlWARN="$cLvlWARN" '
/^----------------------------------------------------/ {block=1; next}
/^$/ && block {exit}    # if there is only one data block pattern - exit
                        # otherwise just reset block to 0 to find next block
block { your code on the block }'
因此,为了重现您的示例:

awk -v lLvlCRIT="$cLvlCRIT" -v lLvlWARN="$cLvlWARN" '
/^----------------------------------------------------/ {block=1; next}
/^$/ && block {exit}
block {if ( $3 >= lLvlCRIT )
     printf("%11s%30s%10s%10s\n", "CRITICAL",$1,$3,$4)       
else if ( $3 >= lLvlWARN )
     printf("%11s%30s%10s%10s\n", "WARNING",$1,$3,$4)  }' file
WARNING                           AAA     92.19  10102320
WARNING                           BBB     91.99    524160
WARNING                           CCC     91.75   1687440
WARNING                           DDD     91.58    816720
WARNING                           EEE     90.93    149760
WARNING                           FFF     90.78   6934080
WARNING                           GGG     90.49   7273440

这里主要关注的是什么是
awk
的有效输入。下面的解决方案使用标志是一种方法。这还考虑了您输入的特定模式

crit=95
warn=90
awk -v crit=$crit -v warn=$warn '
/^DatabaseName/{flag=1;next}
{$2=""}!flag{next}
$3>crit{printf "Critical\t\t%s%s",$0,ORS;next}
$3>warn{printf "Warning \t\t%s%s",$0,ORS}' DatabaseOutput.lo

Warning          AAA  92.19 10102320
Warning          BBB  91.99 524160
Warning          CCC  91.75 1687440
Warning          DDD  91.58 816720
Warning          EEE  90.93 149760
Warning          FFF  90.78 6934080
Warning          GGG  90.49 7273440


Sidenote:但可以肯定的是,对于TB大小的文件来说,
awk
方法会很慢。

遵循
awk
也可能对您有所帮助

awk -v cLvlCRIT="$cLvlCRIT" -v cLvlWARN="$cLvlWARN" -v space="                           " '
/^$/||/^+/{
  flag="";
  next
}
/^----------/{
  flag=1;
  next
}
flag && $3>=cLvlWARN{
  val=$1 OFS $3 OFS $4;
  printf("%s"space"%s\n",$3>=cLvlCRIT?"CRITICAL":($3>=cLvlWARN && $3<cLvlCRIT?"WARNING":""),val)
}
'   Input_file
awk-v cLvlCRIT=“$cLvlCRIT”-v cLvlWARN=“$cLvlWARN”-v space=“”
/^$/||/^+/{
flag=“”;
下一个
}
/^----------/{
flag=1;
下一个
}
标志&&$3>=cLvlWARN{
val=1美元/s$3美元/s$4;

printf(“%s”空格“%s\n”,$3>=cLvlCRIT?“CRITICAL”):$3>=cLvlWARN&&$3Google uooc,永远不要使用范围表达式,因为它们会使琐碎的任务稍微简短一些,但随后需要完全重写或复制更有趣的条件:

awk -v lLvlCRIT="$cLvlCRIT" -v lLvlWARN="$cLvlWARN" '
inBlock {
    if      ( $3 >= lLvlCRIT ) { level = "CRITICAL" }
    else if ( $3 >= lLvlWARN ) { level = "WARNING" }
    else if (NF)               { next }
    else                       { exit }
    printf "%11s%30s%10s%10s\n", level, $1, $3, $4
}
/-------------------/ { inBlock=1 }
' DatabaseOutput.log

对于改进工作代码,您最好的方法是感谢您,将其添加到正确的站点:)您仍然需要
NR>=2{print}
位。当首次匹配
/-/,/^$/
时,您可能需要基于与NR的偏移量实现自己的行计数器。(在本例中,这只是放弃第一个匹配的行。)可能会引用第一行的扩展,只是为了确保我们正在演示其他情况下的最佳实践。@CharlesDuffy True,谢谢。我只是不假思索地复制了第一行,并发布了我脑海中出现的第一个解决方案……我更喜欢其他答案,甚至可能会删除这个:)不要删除--这是一个可靠的答案,也是第一个答案。您可能想添加
/^-/,/^$/
正在做的事情。在awk中使用sed-like范围运算符可能很棘手,但这不是其中之一。对于肌肉记忆,使用awk,使用标志通常比使用范围运算符麻烦少一点。请参阅不要使用范围表达式。请参阅duplicate测试你的代码中的
^-
^$
cat foo | grep…
grep…@CharlesDuffy Done!:)Matias,Charles感谢大家的投入。我想减少使用的命令数量和awk传递次数。因此,我没有使用你的解决方案,尽管它确实有效嗯:)@EdMortan我的代码中没有使用cat,我是直接将数据库查询输出重新定向到awk。不过,我肯定是错误地将其添加到我的工作代码中。我的代码中没有使用cat,我是直接将数据库查询输出重新定向到awk。感谢您对cat和重复条件的建议。您的建议是最受欢迎的感谢Ravinder,你的答案给了我想要的结果。三元运算符也很酷。我发现PesaThe和Ed Mortan的答案更容易理解,因此将使用他们的答案。